在 deinit 中清除强引用是否是正确的模式?

Is cleaning up strong references in deinit a correct pattern?

有几个资源(blog, ,而且我看到它到处都在使用)建议从 [=13= 的 deinit 中的 NotificationCenter 中删除一个观察者],例如:

deinit {
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

现在,根据 another blog entry,我不必关心从 NotificationCenter 中删除观察者,因为它使用 weak 引用,我已经看到与其他参考资料。

困扰我的问题。根据官方documentation:

A deinitializer is called immediately before a class instance is deallocated. You write deinitializers with the deinit keyword, similar to how initializers are written with the init keyword. Deinitializers are only available on class types.

这是否意味着如果仍然存在对 class 的强引用,deinit 将不会被调用,从而使 deinit 引用清理无用?如果 NotificationCenter 仍然有对 viewController 的强引用,那么 viewControllerdeinit 将永远不会被调用,对吗?因此,删除 deinit 中的强引用永远不会真正起作用。

我是不是漏掉了什么?

这条语句

[...] that recommend removing an observer from the NotificationCenter in the deinit of the UIViewController [...]

过去是真的。

还有你的声明

[...] if there still is a strong reference to the class, deinit will not get called.

正确。

观察者参考弱

一个观察者持有一个weak reference目标对象。

这解释了为什么一个对象的 deinit 即使有多个活跃的观察者也会被调用。

那么为什么我们要在 deinit 中删除观察者?

在 iOS9 之前需要这样做,以防止观察者调用已释放对象的方法。

然而,从 macOS 10.11 和 iOS 9.0

开始不再需要注销观察者

In OS X 10.11 and iOS 9.0 NSNotificationCenter and NSDistributedNotificationCenter will no longer send notifications to registered observers that may be deallocated.

Source