在ARC中,我们需要显式发送removeObserver吗?

16

如果一个对象已经被添加为NSNotificationCenter的观察者,我们是否需要显式发送removeObserver:

我有点困惑,无法找到确切的答案。

请详细说明这个问题,包括为什么我们需要显式地删除观察者,以及为什么编译器不会在类/应用程序中隐式放置它。

4个回答

13

是的,如果你不调用removeObserver:,那么被观察的类可能会调用所有已释放的观察者实例。


2
那么为什么ARC不采取预防措施呢?就像它放置[... release]; 为什么它不放置[... removeObserver:...]? - Anoop Vaidya
7
当然,NSNotificationCenter知道谁在观察:毕竟它必须转发通知。看起来他们本可以使用零弱引用来确保通知不会发送到已释放的观察者。但是我进行了一个快速演示来进行双重检查,如果您在dealloc中不调用removeObserver:,它将崩溃。糟糕。 - davehayden
这并不是必需的,因为观察者可以有一个弱引用,但除非苹果明确说明不需要,否则就是必要的。也许这是我们需要提出的一个功能请求。 - Nathan Day
如果您将观察者添加到AVPlayerItem中,是否也需要将其删除?一旦项目完成播放(AVPlayerItemDidPlayToEndTimeNotification),它将自动从播放器中删除。在此之前,我需要手动删除观察者吗? - Oren
你应该编辑你的答案,考虑到在 deinit 上不再需要 removeObserver。(至少适用于针对 iOS 9 或更高版本的应用程序。) - Glenn Howes

8

从10.11开始,观察者在释放它们的销毁方法中不再需要取消注册。

NSNotificationCenter和NSDistributedNotificationCenter不再向已注册的观察者发送可能被解除分配的通知。如果观察者可以存储为零弱引用,则底层存储将观察者存储为零弱引用。或者,如果对象无法弱存储(因为它具有自定义保留/释放机制,这将阻止运行时能够弱存储对象),则该对象将作为非弱零引用存储。这意味着观察者不需要在其销毁方法中取消注册。[1]


谢谢Parag在这里添加了这个。我之前也不知道这个。 - Anoop Vaidya
1
随着时间的推移和旧的SDK逐渐淘汰,与其他答案相比,这个答案变得更加正确。可惜它被列为最后一个答案。 - otto
2
这在iOS9中也是正确的(但不适用于iOS8)。参考:http://useyourloaf.com/blog/unregistering-nsnotificationcenter-observers-in-ios-9/ - Bradley Thomas

5

移除观察者始终是个明智的选择。 如果不移除观察者,即使对象已被释放,消息仍然会被发送。它甚至可能附加到另一个对象上,这肯定会导致严重问题。


如果你的目标是 iOS 9 及以上版本,那么这并不是必需的,因为几乎所有人都会使用这些版本。 - Glenn Howes

2

在使用KVO和Notifications时,您始终需要删除观察者。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接