iPhone - dealloc - Release vs. nil

Posted

技术标签:

【中文标题】iPhone - dealloc - Release vs. nil【英文标题】: 【发布时间】:2010-11-30 07:11:56 【问题描述】:

想知道有经验的人是否可以对此进行更多解释。我见过……的例子

  [view release];

  view = nil;  

....在(void)dealloc中。

有什么区别,一个比另一个更好? 最好的方法是什么?

在进行 retainCount 测试时,我个人看到 nil 将计数从 3 降至 0,但 release 仅将其从 3 降至 2。

【问题讨论】:

【参考方案1】:

你看到的大概是这些:

1) [foo release];
2) self.bar = nil;
3) baz = nil;

    正在释放对象,通过实例变量foo访问它。实例变量将成为一个悬空指针。这是dealloc中的首选方法。

    正在将 nil 分配给 self 上的属性 bar,这实际上将释放该属性当前保留的任何内容。如果您有属性的自定义设置器,请执行此操作,它应该清理的不仅仅是支持属性的实例变量。

    将用 nil 覆盖引用对象的指针baz,但不会释放对象。结果是内存泄漏。永远不要这样做。

【讨论】:

所以在 viewDidLoad 中使用数字 3 不会释放 alloc 对象的内存? 不,它使用 3) 永远不会释放内存,除非你在 Mac OS X 上的垃圾回收 obj-C 中。 执行 self.bar = nil 也会导致内存泄漏。如果该属性被定义为@retain,它将按预期工作;如果你将它定义为@copy,那么你就有内存泄漏。 @AlBlue:不,它不会导致内存泄漏。使用保留或复制将具有相同的语义操作系统来释放属性引用的先前对象。唯一的区别是如何获取新值; ´ivar = [newValue retain];` 与 ivar = [newValue copy]。两者都将使用简单的[ivar release] 释放旧值。 使用 2) 可能很危险,这就是首选 1) 的原因。如果 setter 被子类覆盖,则现在正在调用已调用 dealloc 方法的子类中的方法。安全属性/ivar 访问的一般规则是: 1) 直接在 initdealloc 和 setter/getter 中使用 ivar。 2) 所有其他访问都应通过该属性进行。【参考方案2】:

如果您不使用属性(其中 self.property = nil 也会释放一个对象),那么您应该始终遵循将引用设置为 nil 的代码的发布,如您所述:

[view release]; view = nil;

原因是它避免了可以使用无效引用的可能性。这种情况很少见且很难发生,但它可能会发生。

这在 viewDidUnload 中更为重要,如果您正在释放 IBOutlets - 这是一个更现实的场景,其中引用可能会因为内存警告卸载视图而变坏,然后视图中的一些其他代码试图使用重新加载视图之前的引用。

基本上,这只是一种很好的做法,如果您养成这样做的习惯,它会在某个时候为您避免崩溃。

【讨论】:

所以本质上对于具有属性的 ivars,我们可以这样做吗? - (void)dealloc self.iVar = nil 你可以,虽然你过去被告知不要在 dealloc 中使用设置器,以免产生副作用......但现在内部类变量可以在你必须使用设置器的地方自动创建,我想在dealloc中使用该方法将变量设置为nil是可以的。 你仍然可以引用合成的实例变量,你不必在dealloc中使用setter。 很好,实际上你不应该在 dealloc 中使用 setter。【参考方案3】:

@bbullis22 您已经看到重新染色计数从 3 下降到 0,因为您将引用设置为 nil。然后你要求'nil'的retaincount为零。但是,曾经被引用的对象具有相同的保留计数 - 1(由于将引用设置为 nil)。 使用 release,引用仍然引用同一个对象,这就是为什么在这种情况下您会看到保留计数从 3 下降到 2。

【讨论】:

【参考方案4】:

就代码中的用法而言,在您的 dealloc 中,您不需要对属性进行赋值,只需 releasing 即可。

- (void)dealloc 
    [myProperty release]; // don't need to assign since you won't have the object soon anyway
    [super dealloc];

【讨论】:

等等,最后一行不应该是 [super dealloc] 吗?【参考方案5】:

我认为同时使用两者是一种安全网。仅使用release,如果您搞砸了引用计数管理,您可能会遇到问题。您将释放一个对象,将其内存还给系统,但指针仍然有效。

使用nil 可以保证程序不会崩溃,因为向nil 发送消息什么都不做。

【讨论】:

您建议两个都调用?发布前为零,反之亦然? 在释放之前分配 nil 意味着您将释放发送给 nil(因此不释放对象)。分配给 nil 是可选的(当对象被释放时,实例变量不应该被再次引用)

以上是关于iPhone - dealloc - Release vs. nil的主要内容,如果未能解决你的问题,请参考以下文章

Iphone:定制的 UIView 是不是需要 dealloc

iPhone SDK:Dealloc 与 Release?

iPhone - dealloc - Release vs. nil

Cocos2d-iphone,替换场景时不调用dealloc

iPhone 内存释放问题

UIPopoverController:在popover仍然可见时达到了dealloc