底部更新。
使用(保留)合成属性时,执行 dealloc 职责的最佳方法是将属性设置为 nil。我之所以说这是“最好”的方式,是因为它可以确保满足财产声明所暗示的所有合同。例如,如果您的属性被声明为原子的(除非您特别声明它是非原子的),那么保证在 dealloc 上取消设置此属性的唯一方法是使用相同的原子保证将其设置为 nil 使用dealloc 中的属性。这也意味着它对于对象的任何 Key-Value Observations 都会正确运行 - 这可能很重要,特别是如果您使用 Cocoa Bindings。
在为没有相应属性的(可能是私有的)实例变量进行自己的内存管理时,有几个习惯用法。最简单但最危险的方法是简单地释放 iVar,如下所示:
- (void)dealloc
{
[myArray release];
[super dealloc];
}
这将导致 iVar 上的保留被释放,但正如其他人所提到的,将留下现在可能陈旧的指针,如果错误,可能会被陈旧或非保留的指针访问,这些指针可能存在指向正在被访问的对象解除分配。接下来是另一个答案建议的成语:
- (void)dealloc
{
[myArray release], myArray = nil;
[super dealloc];
}
一个更安全、更迂腐的习语是:
- (void)dealloc
{
id temp = myArray;
myArray = nil;
[temp release];
[super dealloc];
}
这通过在释放指向的对象之前清除 iVar 进一步限制了指针过时读取的机会。但是,由于指令重新排序的可能性,即使这也不能 100% 保证在所有架构上都不会出现过时的读取。
尽管关于并发和内存管理的话题还有很多话要说,但总的来说,如果你有一个 @synthesized 属性设置器,你应该只在 dealloc 中使用它。这样做意味着如果您更改 @property 的行为,则对于 @property 声明,dealloc 行为将自动正确。
重要提示:使用原子属性!= 线程安全。(事实上,如果你问我原子属性是一种浪费,但是......)更多细节请看这里。
更新
这最近再次得到了投票,虽然我支持我在这里所说的关于具有综合保留属性的原子保证,并且原始答案中的一些其他内容本身就有价值,但我觉得有必要告诉另一方故事。Dave DeLong 在评论中提到了其中的一些内容,但我认为值得在主要答案中添加细节。
我认为保持原子性保证的唯一方法是nil
通过 setter 将属性设置为。但是您不应该关心,原因如下:如果正在dealloc
编辑对象,则意味着(如果您的对象图是正确的)不应该有对该对象的活动引用。如果没有对对象的活动引用,那么任何人都不可能关心清除属性的操作的原子性保证。
我还在原始答案中提到了 KVO 作为使用 setter in 的原因dealloc
,但 Dave DeLong 在评论中提到了 KVO 作为对位。他是对的,原因如下:同样,如果一个对象正在被dealloc
编辑,那么所有的 KVO 观察者都应该已经被移除了(同样,应该没有活的引用,不管 KVO 与否)。事实上,如果不是这种情况,不久之后您就会看到一条控制台消息,告诉您您的对象消失了,但观察结果仍然存在。
简而言之,虽然您不能使原子性保证等同于 in 中的合成 setter 的保证dealloc
,但它永远不重要(如果确实如此,其他东西就会被破坏。)