【问题标题】:iPhone ridiculous memory leaksiPhone荒谬的内存泄漏
【发布时间】:2011-11-03 07:39:20
【问题描述】:

我的 iphone 应用程序中的内存泄漏问题已经困扰我很久了。我觉得我必须错误地阅读我的数据。似乎每当我在其中分配内存时,都会有太多开销导致泄漏,以至于当我释放数据时,我的内存使用量几乎不会下降或根本不会下降。一个浪费了 2 天的时间是我的翻转视图控制器上的 UIWebview 加载了一个 url,我的应用程序的内存使用量从 3 mb 跳到了 7。我在我的 dealloc 方法中释放了 webview,但巨大的内存块仍然存在。有没有人有什么建议。

- (void)viewDidLoad {
self.view.backgroundColor = [UIColor viewFlipsideBackgroundColor];

nav_bar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0,0,self.view.frame.size.width+20,45)];
[self.view addSubview:nav_bar];
[UINavigationBar release];

rightButton = [[UIBarButtonItem alloc] initWithTitle:@"Done" style:UIBarButtonItemStyleDone target:self action:@selector(done)];
item = [[UINavigationItem alloc] initWithTitle:@"Flipside View"];
item.rightBarButtonItem = rightButton;
item.hidesBackButton = YES;
[nav_bar pushNavigationItem:item animated:NO];
[rightButton release];
[item release];

NSAutoreleasePool *initPool = [[NSAutoreleasePool alloc] init];

web_view = [[UIWebView alloc]initWithFrame:CGRectMake(0,45,self.view.frame.size.width,self.view.frame.size.height - 45)];

web_view.autoresizesSubviews = YES;
web_view.autoresizingMask=(UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth);

NSString *urlAddress = @"http://www.tutorialpark.com/wpcontent/uploads/3/HeartBlending.jpg";
NSURL *url = [NSURL URLWithString:urlAddress];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];

[web_view loadRequest:requestObj];
[self.view addSubview:web_view];
[web_view release];
[initPool release];

[super viewDidLoad];
}

- (void)dealloc {
   [nav_bar removeFromSuperview];
   [web_view removeFromSuperview];
   [rightButton release];
   [super dealloc];
}

对于我现在非常生气并且不想处理它的缩进,我深表歉意。

【问题讨论】:

  • 顺便说一句,我在模拟器和真实设备中都看到了这些泄漏

标签: iphone memory-leaks uiwebview overhead


【解决方案1】:

您似乎对引用计数的工作原理感到困惑。

参见下面的 cmets:

- (void)viewDidLoad {
  self.view.backgroundColor = [UIColor viewFlipsideBackgroundColor];

  UINavigationBar* nav_bar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0,0,self.view.frame.size.width+20,45)];
  // nav_bar retaincount 1
  [self.view addSubview:nav_bar];
  // nav_bar retaincount 2
  [nav_bar release];
  // nav_bar retaincount 1 - now controlled by self.view

  UIBarButtonItem* rightButton = [[UIBarButtonItem alloc] initWithTitle:@"Done" style:UIBarButtonItemStyleDone target:self action:@selector(done)];
  // rightButton retaincount 1

  UINavigationItem* item = [[UINavigationItem alloc] initWithTitle:@"Flipside View"];
  // item retaincount 1

  item.rightBarButtonItem = rightButton;
  // rightButton retaincount 2

  [rightButton release];
  // rightButton retaincount 1 - now controlled by item

  item.hidesBackButton = YES;
  [nav_bar pushNavigationItem:item animated:NO];
  // item retaincount 2

  [item release];
  // item retaincount 1 - now controlled by nav_bar

  UIWebView* web_view = [[UIWebView alloc]initWithFrame:CGRectMake(0,45,self.view.frame.size.width,self.view.frame.size.height - 45)];
  // web_view retaincount 1

  web_view.autoresizesSubviews = YES;
  web_view.autoresizingMask=(UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth);

  NSString *urlAddress = @"http://www.tutorialpark.com/wpcontent/uploads/3/HeartBlending.jpg";

  NSURL *url = [NSURL URLWithString:urlAddress];
  // url is autoreleased, you can ignore..

  NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
  // requestObj is autoreleased, you can ignore..

  [web_view loadRequest:requestObj];

  [self.view addSubview:web_view];
  // web_view retaincount 2

  [web_view release];
  // web_view retaincount 1 - now controlled by self.view

  [super viewDidLoad];
}

- (void)dealloc {
   // don't need to do anything because all the memory is controlled by self.view, will be released when the internal variable self.view is released.
   [super dealloc];
}

【讨论】:

  • 感谢您为我清除了一些东西,但是在我关闭 filpside 视图后,webview 加载的数据仍然存在。它很好,因为它不必重新加载 url,但我希望它不再被缓存在内存中。有没有办法释放加载到 webview 中的数据,我认为这可以通过 webview 解除分配来完成,但根据我方便的分配图,它不是。
  • 最好将保留计数视为增量;您添加和减去保留计数。在上面,cmets 很可能是不正确的——retain count 可能是 2,可能是 5,可能是 492,重要的是 没关系。您应该担心您造成的保留。
  • 确实,计数可能是任何东西,但它更多的是作为一个粗略的心理指南,了解计数会在哪里发生变化以及在哪里发生粗略的所有权转移。
  • 快速搜索发现 UIWevView 实际上可能正在泄漏内存:stackoverflow.com/search?q=UIWebView+memory+leak
【解决方案2】:

[UINavigationBar 发布]; - 这是在做什么?是否意味着 [nav_bar release] ? - 如果是这样,则应稍后在您再次访问 nav_bar 的代码稍远的地方完成。但是,它似乎是一个成员变量?所以应该在dealloc中释放。

rightButton 被释放两次 - 一次在 viewDidLoad 中,一次在 dealloc 中。

您能解释一下自动释放池的用途吗?

【讨论】:

  • 自动释放池是一段旧代码遗留下来的,我发帖时一定看过它