Objective-C保留问题

时间:2011-04-12 12:37:40

标签: objective-c xcode memory memory-management

在Xcode中我有一个UINavigationController,我推了一个UIViewController。

在那个UIViewController中我初始化一个UIScrollView。

一切都很好。

然而,在切换到另一个视图后,我记录了控制器的保留计数,令我惊讶的是它是一个而不是零。

以下是代码:

scroller = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];

[self.view addSubview:scroller];

- (void)dealloc {
    [super dealloc];

    NSLog(@"retaincount, %d", [scroller retainCount]);  //displays 2

    [scroller release];

    NSLog(@"retaincount, %d", [scroller retainCount]); // displays 1
}

我只启动它并将其添加到UIViewControllers视图。

亲切的问候,

汤姆

4 个答案:

答案 0 :(得分:4)

不要使用retainCount!来自apple documentation

  

重要:此方法在调试内存管理问题时通常没有价值。因为任何数量的框架对象可能保留了一个对象以保存对它的引用,而同时自动释放池可能在对象上保留任意数量的延迟版本,所以您不太可能从此获取有用信息方法。

     

要了解您必须遵守的内存管理的基本规则,请阅读“Memory Management Rules”。要诊断内存管理问题,请使用合适的工具:

     
      
  • 即使在运行程序之前,LLVM/Clang Static analyzer通常也会发现内存管理问题。
  •   
  • Instruments应用程序中的Object Alloc仪器(请参阅Instruments User Guide)可以跟踪对象分配和销毁。
  •   
  • Shark(请参阅Shark User Guide)还介绍了内存分配(在程序的众多其他方面)。
  •   

话虽如此:您必须在[super dealloc]方法的最后一行调用dealloc。除此之外,代码中的所有内容都应该没问题。不要尝试手动降低retainCount。使用适当的内存管理。再说一遍,不要看看retainCount。

释放后不允许使用对象。如果由于您的释放而将释放滚动条,则第二个NSLog将导致BAD_ACCESS异常。

答案 1 :(得分:1)

这就是原因:

scroller = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
//retain count = 1

[self.view addSubview:scroller];
//retain count + 1 + 1 = 3

//later the AutoreleasePool decrements the count by 1, resulting in a retain count of 2.
  1. init…开头的方法 返回非自动释放的实例 保留计数为1。
  2. 访问您的 子视图通过self.view:返回一个自动释放的保留指向子视图的指针。
  3. 添加 通过addSubview: retains the subview
  4. 查看视图
  5. 通过removeFromSuperview: releases it
  6. 从其超级视图中删除子视图

    您不应该依赖对象的保留计数。
    相反,您必须注意保持和释放对象的调用 请务必在此问题上阅读Apple的Memory Management Programming Guide! (特别是rules section!)

答案 2 :(得分:1)

self.view正在保留它。当您的UIViewController deallocs时,它将释放self.view,它将释放所有保留的子视图。实际上,您可能应该在将其添加到self.view之后立即将其发布。

那就是说,我强烈第二个@ fluchtpunkt的回答。检查retainCount属性以查找调试信息只会导致Stack Overflow上的混乱和日益连贯的帖子。

答案 3 :(得分:1)

以前的答案是正确的:不要使用-retainCount,并确保在自己的-dealloc实现中最后调用[super dealloc]

我想补充一点,你可能永远不会看到一个案例(不是你应该看的),其中-retainCount返回0.如果一个对象的retainCount降为零,则该对象被释放。实际上,似乎Cocoa甚至都没有把retainCount设置为零...如果之前的retainCount为1,则释放似乎解除对象。还有一个理由认为-retainCount是私有实现细节。