我对属性的内存管理有一般性问题。目前,我总是使用属性而没有任何明确的相关ivars声明。而且,对于每个保留或复制的属性,我都在dealloc和viewDidUnload方法中释放它的保留计数:
-(void)dealloc{
[self.myProperty release];
[self.myOutlet release];
[super dealloc];
}
- (void)viewDidUnload{
[super viewDidUnload];
self.myProperty = nil;
self.myOutlet = nil;
}
现在,我知道只有主视图保留的出口和属性应该在viewDidUnload中设置为nil,其余的属性应该在dealloc中释放。但是,嘿,为什么我必须为每个必须释放的属性而烦恼 - 在dealloc或viewDidUnload中?如果某些属性将被释放两次就可以了,因为它不会通过向nil对象发送消息来使应用程序崩溃。在两个地方放置发行版(dealloc和unload)可以节省时间并防止以后在进行代码重构和忘记更改发布位置时出现错误。有人批评并大喊大叫吗? :)
答案 0 :(得分:1)
如果您在-dealloc中使用属性访问器,因为您无法直接访问ivar,那么您应该在-viewDidUnload中执行相同的-dealloc:
self.myProperty = nil;
在-dealloc中使用-release的目的是避免调用访问器,当子类中的所有其他内容已经存在时,可以被子类覆盖,以便在-dealloc中具有您不想要的副作用。被解除分配。但是如果你已经在-dealloc中调用了访问器,你也可以使用setter来释放ivar并确保它正确完成。
-dealloc和-viewDidUnload之间的区别在于你仍在使用-viewDidUnload中一个完整的,功能齐全的对象,而该对象可能已经在-dealloc中被部分解除分配。
答案 1 :(得分:1)
我的previous answer讨论了Apple推荐的内容以及原因。为清楚起见,此处转载了相关部分:
此外,来自-viewDidUnload
上的Apple docs:
放弃任何对象(包括出口中的对象)的所有权的首选方法是使用相应的访问器方法将对象的值设置为nil。但是,如果您没有给定对象的访问器方法,则可能必须显式释放该对象
所以,你去吧。如果你的插座有一个与之相关的属性(它们都应该已经存在),那么在-viewDidUnload
中将其取消 - 但不要释放它。当您考虑合成访问器中实际发生的情况时,这是有意义的;代码看起来像这样:
- (void) setMyView1 : (UIView *) view {
if (myView1) // the associated IVAR is already set
[myView1 release];
myView1 = [view retain];
}
如您所见,将synthesize属性设置为nil会隐式释放保留的对象。
同样来自关于-dealloc
的文档:
如果您实现此方法但正在为iOS 2.x构建应用程序,则dealloc方法应释放每个对象,但在调用super之前还应将该对象的引用设置为nil。
除非您支持iOS2.x,否则无需在dealloc中将对象设置为nil。
因此,总结一下Apple关于-viewDidUnload
和-dealloc
的文档:
-viewDidUnload
中,nil属性(包括IBOutlet属性),但不释放它们-dealloc
版本属性中,但不为零(除非为2.x构建)。