【问题标题】:Is setting a retained property to nil enough?将保留属性设置为 nil 是否足够?
【发布时间】:2014-06-05 01:52:08
【问题描述】:

我看到一些代码

@property (nonatomic, readwrite, retain) id something;

他们合成了它:

@synthesize something = something_;

在构造函数中:

self.something = @"HELLO!";

我认为,上面的行有效地保留了该字符串。

但是,在他们的 dealloc 方法中,他们这样做:

[self setSomething:nil];

我想这很好,因为我想象当你将一个属性设置为 nil 时,旧的值就会被释放。但是后来,我注意到他们所做的所有其他课程都有类似

[something release];

相反,所以我不再确定。两种方式都正确吗?

【问题讨论】:

  • @raurora - 该线程非常古老,与 ARC 等无关。
  • self.something = nil; 与 ARC 无关,retained 与 ARC 无关。
  • 您真正应该做的是切换到 ARC。说真的。

标签: ios objective-c


【解决方案1】:

简答:使用 ARC。它会为你处理这些事情。它更不容易出错,并且与手动引用计数一样快。

更长的答案:

如果您使用保留属性,那么是的,将 属性 设置为 nil 是正确的做法。

像这样:

self.something = nil;

之所以有效,是因为保留属性的设置器首先释放旧值,然后保留新值并将其分配给属性的 iVar。由于新值为零,因此保留什么也不做。

如果在你的第二个例子中:

[something release];

something 是属性的 iVar,如果在对象的 dealloc 方法的代码之外的任何地方调用此代码,则将来会导致崩溃。原因是这会释放对象,但不会将 iVar 归零。稍后,当具有某属性的对象被释放时,它的 dealloc 方法就会触发。 dealloc 方法中的代码应该尝试释放对象的保留属性。向已释放的对象发送释放会导致崩溃。

在您的情况下,您是在询问 dealloc 方法中的代码。在 dealloc 中,调用[something release] 并将属性设置为 nil 与释放对象的结果相同。不过,调用 setter 可能更安全,因为自定义 setter 有时会有其他代码带有额外的“副作用”。由于您正在编写 dealloc 方法,因此您应该是该类的作者,并且应该了解 setter 方法中的任何特殊代码。

现在,如果something 是一个实例变量,而不是一个属性,那么正确的做法是

[something release]
something = nil;

于 2014 年 6 月 5 日编辑,讨论 dealloc 方法中的代码案例。

【讨论】:

  • "在 dealloc 中它会尝试释放它的保留属性。"错了。
  • @mifki 不,绝对没有错。在手动引用计数中,您必须编写您的 dealloc 方法来释放所有保留的属性。如果你不这样做,你就会泄漏。
  • 哦,我以为你的意思是自动释放保留的属性。问题本身也与dealloc有关,因此在这种特殊情况下,将不再有“稍后,当对象被释放时”。
  • 天哪。我错过了 OP 问题中的那一点:“但是,在他们的 dealloc 方法中,他们这样做了......”是时候编辑我的答案了。
【解决方案2】:

最好使用[something_ release]。这不会导致调用 setter,否则可能会导致执行一些在 dealloc 中不需要的操作。

【讨论】:

    【解决方案3】:

    两者都是正确的,[self setSomething:nil]; 会更好,当something 释放为 0 时,retainCount 然后释放。这可以防止使用 something 与 BAD_EXE 发生崩溃。

    正如 mifki 所说,如果使用 [self setSomething:nil]; 则调用 setter;所以这取决于你在 setter 方法中做了什么,一个好的 setter 应该关心 set value 为 nil,并正确处理这种情况,并且不会不受欢迎。

    即使setter方法实现不能总是设置为nil,更好的发布风格应该是:

    [something_ release], something_ = nil;  //this should be safely release always
    

    【讨论】:

    • 嗨,mifki 的回答说[something_ release] 更好。我不知道你们是否可以澄清这种差异。谢谢!
    • @JustKidding 通常在dealloc 你,好吧,只是解除分配的东西。所以没有代码可以访问已发布但不能访问的属性。此外,如果您对属性使用自定义设置器,例如,触发重绘、重新计算某些内部值或类似的东西,您不希望从 dealloc 执行这些操作。
    • @JustKidding 我已经编辑了我的答案。希望能帮到你。
    • “一个好的设置器应该关心设置值为零” - 我想@synthesize生成的默认设置器确实会处理这个问题?
    • @JustKidding 由@synthesize 生成像这样:if(something_ != newThing){ [something_ release]; something_ = [newThing retain]; } 它就像:[something_ release], something_ = nil;
    猜你喜欢
    • 2011-12-15
    • 1970-01-01
    • 2012-08-17
    • 2011-06-05
    • 1970-01-01
    • 2016-11-03
    • 1970-01-01
    • 2017-03-05
    • 1970-01-01
    相关资源
    最近更新 更多