在Swift中删除NSNotification观察者的位置?

Cle*_*eph 72 nsnotifications ios swift

我应该在哪里删除NSNotificationSwift 中的观察者,因为viewDidUnload并且dealloc()不可用?

Nik*_*vic 114

iOS 9(和OS X 10.11)开始,如果你没有使用基于块的观察者,则不需要自己删除观察者.系统将为您完成,因为它可以为观察者使用归零弱引用.

如果您正在使用基于块的观察者,请确保在闭包的捕获列表中使用自身弱[weak self]捕获,并在方法中删除observerdeinit.如果你不使用对self的弱引用deinit,那么将永远不会调用方法(从而删除那个观察者),因为Notification Center将无限期地保留对它的强引用.

可以在OS X v10.11和iOS 9的Foundation Release Notes中找到更多信息.

如果观察者能够存储为归零弱引用,则底层存储将把观察者存储为归零弱引用,或者如果对象不能被弱存储(即它具有可以阻止运行时的自定义保留/释放机制)从能够弱对象存储对象,它将对象存储为非弱的归零引用.这意味着观察者不需要在他们的释放方法中取消注册.

基于块的观察者通过 - [NSNotificationCenter addObserverForName:object:queue:usingBlock]方法仍然需要在不再使用时取消注册,因为系统仍然拥有对这些观察者的强引用.


Kam*_*pai 63

使用以下方法,其功能相同dealloc.

deinit {
    // Release all resources
    // perform the deinitialization
}
Run Code Online (Sandbox Code Playgroud)

在取消分配类实例之前立即调用deinitializer.您使用deinit关键字编写deinitializers,类似于使用init关键字编写初始化器的方式.Deinitializers仅适用于班级类型.

Swift Deinitializer

  • 从iOS 9开始,根据下面的答案,除非您使用基于块的观察者,否则将自动删除观察者. (8认同)

Pab*_*uan 51

您可以使用三种方法:

1 - 后popViewController,后navigationControllerdismissViewControllerAnimated:

deinit {
    print("Remove NotificationCenter Deinit")
    NSNotificationCenter.defaultCenter().removeObserver(self)
}
Run Code Online (Sandbox Code Playgroud)

要么

2 - viewDidDisappear,在它已经是下一个视图控制器后删除:

override func viewDidDisappear(animated: Bool) {
    NSNotificationCenter.defaultCenter().removeObserver(self)
}
Run Code Online (Sandbox Code Playgroud)

要么

3 - viewWillDisappear- 在打开下一个视图之前:

override func viewWillDisappear(animated: Bool) {
    NSNotificationCenter.defaultCenter().removeObserver(self)
}
Run Code Online (Sandbox Code Playgroud)

Swift 3.0语法:

NotificationCenter.default.removeObserver(self)
Run Code Online (Sandbox Code Playgroud)

  • 我想 deinit 是最好的选择。 (2认同)

Ash*_*hal 12

在Swift 4.2中,这是删除观察者的方法之一

deinit {
    NotificationCenter.default.removeObserver(self, name: Notification.Name.Identifier, object: nil)
}
Run Code Online (Sandbox Code Playgroud)

在viewDidLoad类中设置addObserver通知

override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(self, selector: #selector(didReceivedItemDetail), name: Notification.Name.Identifier, object: nil)
}
Run Code Online (Sandbox Code Playgroud)

  • @GordonW 如果您的 deinit 方法在视图控制器生命周期结束时没有被调用,那么该类中存在内存问题。 (4认同)
  • 请注意,在慢速网络条件和某些用户活动(即在繁忙的视图操作期间离开)可能不会调用 deinit。我在测试中看到过这一点。 (2认同)