【问题标题】:autorelease vs. release in dealloc自动释放与释放释放
【发布时间】:2011-11-09 17:37:54
【问题描述】:

我知道 iOS 中的内存管理对于像我这样的新手来说很棘手,但我希望在 stackoverflow 上有一个清晰的解释,这是我在其他任何地方都找不到的。

所以,假装我有一个属性 / ivar

@property(nonatomic, retain) UIPopoverController *popOver;

我是这样分配的:

self.popOver = [[[UIPopoverController alloc] initWithContentViewController:popOverContent] autorelease];    

现在,在我的 dealloc 和 viewDidUnload 方法中,我都这样做了

// in viewDidUnload:
self.popOver = nil;
// in dealloc:
[popOver release];

问题:

  1. 如果我在 viewDidUnload/dealloc 中执行 nil/release,我真的需要在分配时自动释放吗?
  2. 反之亦然,如果我在分配时自动释放,我是否需要稍后再取消/释放?
  3. 有什么区别(如果有的话)?

在此先感谢您抽出宝贵的时间 - 我会继续阅读,说真的,内存管理并不是那么难缠您的头...

【问题讨论】:

  • 感谢编辑标题;我看到了类似的问题,前面有“iOS:”;实际上是在没有它的情况下开始的。

标签: objective-c ios autorelease dealloc


【解决方案1】:

不要被这一行的自动释放搞糊涂了:

self.popOver = [[[UIPopoverController alloc] initWithContentViewController:popOverContent] autorelease];

在此声明之后,您实际上拥有该对象,因为属性设置者声称拥有它。自动释放平衡了alloc-init

所以...是的,您需要在分配时自动释放。如果你这样做(没有自动释放),你会泄漏:

self.popOver = [[UIPopoverController alloc] initWithContentViewController:popOverContent];

另一种选择是使用临时变量而不是autorelease

UIPopoverController *temp = [[UIPopoverController alloc] initWithContentViewController:popOverContent];
self.popOver = temp;
[temp release];

无论哪种方式都需要释放dealloc中的对象。

【讨论】:

  • 感谢 Abizern 和 Yuji 以及他们非常有启发性的回答。现在我也理解了 Yuji 的回答中描述的“本地所有权”的概念。无论如何,有什么方法可以测试您的应用程序的内存泄漏(可能使用 Instruments)?
  • @pille 是的,你可以使用Instruments。在 Xcode 中,click and hold the run button 或选择 Product -> Profile。这会弹出一个对话框,您可以在其中选择“泄漏”。
  • @pille 在使用 Instruments 之前,只需执行“分析”即可,它位于 XCode 的“构建”菜单下方。
【解决方案2】:

1 如果我在 viewDidUnload/dealloc 中执行 nil/release,我真的需要在分配时自动释放吗?

是的。

2 反之亦然,如果我在分配时自动释放,我是否需要稍后再 nil / 释放?

是的。

在第一种情况下,自动释放是代表该方法完成的。该方法不再需要弹出框,因此需要(自动)释放它。

dealloc,您的对象不再需要弹出框。因此,您需要释放它。

这很简单。您不必考虑长期的对象所有权;你只需要在每个方法的层面上进行非常本地化的思考。是否释放它的决定根本不取决于该对象是否由程序的其他部分保留。在一个方法中,如果你分配了一个对象并且你不再需要它在那个方法中,你(自动)释放它。

dealloc 是该规则的一个小例外。在那里,您需要释放所有实例变量的所有权。

就是这样!

【讨论】:

    【解决方案3】:
    1. 是的。但在这种情况下可能不是。
    2. 是的。但在这种情况下可能不是。
    3. viewDidUnload 在视图卸载时调用,dealloc 在视图控制器被销毁时调用。

    viewDidUnload 中,您释放了由视图 使用的不再需要的对象,并且可以在viewDidLoad 中重新创建。很明显,由于视图没有被显示,它不需要保留视图控制器为其设置的对象。

    dealloc 中,您正在清理 viewController,在这里您将清理它的所有资源,包括分配给视图的资源。

    在这种情况下,视图不拥有弹出框控制器 - 它应该由视图控制器拥有,因此无需在 viewDidUnload 中释放它,但您需要在 dealloc 中释放它。

    【讨论】:

      猜你喜欢
      • 2011-05-03
      • 1970-01-01
      • 2011-05-08
      • 1970-01-01
      • 1970-01-01
      • 2011-11-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多