如果对象是观察者并在通知中心注册,如何调用 dealloc 方法?

How dealloc method gets called if an object is an observer and registered at notification centre?

考虑一个场景,当一个对象注册到通知中心(假设ios 8),所以中心创建一个对该对象的强引用。由于 <= ios8 center 对对象进行了强引用,因此保留计数增加到 1。现在,Apple 文档说我们需要删除 dealloc() 中的观察者以防止崩溃。我在这里没有得到两件事:

  1. 如果中心仍然保留它,如何调用对象 dealloc() 方法?我的理解是,除非保留计数为零,否则不会在此对象上调用 dealloc()。
  2. 让我们假设 dealloc 发生并且我们没有删除观察者。由于对象已经被释放,为什么它会崩溃?

documentation for addObserver 包含以下注释:

If your app targets iOS 9.0 and later or macOS 10.11 and later, you don't need to unregister an observer in its deallocation method. If your app targets earlier releases, be sure to invoke removeObserver:name:object: before observer or any object specified in addObserver:selector:name:object: is deallocated.

这意味着在 iOS 8 中,观察者被作为 unsafe_unretained 参考。如果在未移除观察者的情况下释放观察者,则随后尝试传递通知将导致异常,因为引用将指向已释放的对象。

在 iOS 9 及更高版本中,观察者作为 weak 参考持有,NotificationCenter 在尝试通知观察者之前检查 nil 的参考。如果您的目标是 iOS 9 或更高版本,那么您不需要显式删除观察者。

unsafe_unretained 引用和 weak 引用都不会增加保留计数,因此使用 NotificationCenter 注册不会阻止观察者被释放。