在 Cocoa 中,在释放对象时,我是否需要从接收 KVO 通知中删除该对象?
题
当我注册一个对象时 富 从另一个对象接收 KVO 通知 酒吧 (使用 addObserver:...),如果我随后解除分配 富 我需要发送一个 removeObserver:forKeyPath:
发消息给 酒吧 在-dealloc 中?
解决方案
你需要使用 -removeObserver:forKeyPath:
删除之前的观察者 -[NSObject dealloc]
运行,所以是的,在 -dealloc
你的班级方法会起作用。
比这更好的是有一个确定性的点,无论拥有正在观察的对象,都可以告诉它它已经完成并且将(最终)被释放。这样,当不再需要进行观察的事物时,您可以立即停止观察,无论它何时实际被释放。
记住这一点很重要,因为 Cocoa 中对象的生命周期并不像某些人想象的那样具有确定性。各种 Mac OS X 框架本身 将要 发送您的对象 -retain
和 -autorelease
, ,延长它们的使用寿命,超出您的想象。
此外,当您过渡到 Objective-C 垃圾收集时,您会发现 -finalize
将在非常不同的时间和非常不同的环境中运行 -dealloc
做过。一方面,终结发生在不同的线程上,所以你真的 不能 安全发送 -removeObserver:forKeyPath:
到另一个对象 -finalize
方法。
坚持内存(和其他稀缺资源)管理 -dealloc
和 -finalize
, ,并使用单独的 -invalidate
让所有者在确定点告诉对象您已完成对它的处理的方法;做诸如删除 KVO 观察之类的事情。您的代码的意图将更加清晰,并且需要处理的细微错误也会更少。
其他提示
我通过痛苦的经历获得的一些额外信息:虽然 NSNotificationCenter 在垃圾回收下运行时使用清零弱引用,但 KVO 却没有。因此,在使用 GC 时,您可以不删除 NSNotificationCenter 观察者(在使用保留/释放时,您仍然需要删除观察者),但您仍然必须删除 KVO 观察者,正如 Chris 所描述的那样。
绝对同意 Chris 的“在 -dealloc 和 -finalize 中坚持内存(和其他稀缺资源)管理”的评论。很多时候我会看到人们试图在他们的 dealloc 函数中使 NSTimer 对象无效。问题是,NSTimer 保留了它的目标。因此,如果该 NSTimer 的目标是 self,则 dealloc 将永远不会被调用,从而导致一些潜在的严重内存泄漏。
无效于 -invalidate
并在你的中进行其他内存清理 dealloc
和 finalize.