在 Cocoa 中,在释放对象时,我是否需要从接收 KVO 通知中删除该对象?

StackOverflow https://stackoverflow.com/questions/13927

  •  08-06-2019
  •  | 
  •  

当我注册一个对象时 从另一个对象接收 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 并在你的中进行其他内存清理 deallocfinalize.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top