ios 在哪里删除 Swift 中 NSNotification 的观察者?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28689989/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 04:57:09  来源:igfitidea点击:

Where to remove observer for NSNotification in Swift?

iosswiftnsnotifications

提问by Clement Joseph

Where should I remove the observer for NSNotificationin Swift, since viewDidUnloadand dealloc()are unavailable?

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

采纳答案by Kampai

Use below method which functions same as dealloc.

使用以下功能相同的方法dealloc

deinit {
    // Release all resources
    // perform the deinitialization
}

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

在释放类实例之前立即调用析构器。使用 deinit 关键字编写析构器,类似于使用 init 关键字编写初始化器的方式。析构器仅适用于类类型。

Swift Deinitializer

Swift 析构器

回答by Nikola Milicevic

As of iOS 9(and OS X 10.11), you don't need to remove observersyourself, if you're not using block based observers though. The system will do it for you, since it uses zeroing-weak references for observers, where it can.

iOS 9(和 OS X 10.11)开始,如果您不使用基于块的观察者,则不需要自己删除观察者。系统会为你做这件事,因为它可以为观察者使用归零弱引用。

And if you are using block based observers, make sure you capture self weaklyusing [weak self]in the closure's capture list, and remove observerin deinitmethod. If you don't use weak reference to self, deinitmethod (and thus removal of that observer) will never be called since Notification Center will hold a strong reference to it indefinitely.

如果您使用基于块的观察者,请确保您在闭包的捕获列表中使用弱捕获自我[weak self],并在方法中删除观察者deinit。如果您不使用对 self 的弱引用,deinit则永远不会调用方法(从而删除该观察者),因为通知中心将无限期地持有对它的强引用。

More info can be found at Foundation Release Notes for OS X v10.11 and iOS 9.

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

If the observer is able to be stored as a zeroing-weak reference the underlying storage will store the observer as a zeroing weak reference, alternatively if the object cannot be stored weakly (i.e. it has a custom retain/release mechanism that would prevent the runtime from being able to store the object weakly) it will store the object as a non-weak zeroing reference. This means that observers are not required to un-register in their deallocation method.

Block based observers via the -[NSNotificationCenter addObserverForName: object: queue: usingBlock] method still need to be un-registered when no longer in use since the system still holds a strong reference to these observers.

如果观察者能够被存储为一个清零弱引用,底层存储会将观察者存储为一个清零弱引用,或者如果对象不能弱存储(即它有一个自定义的保留/释放机制,会阻止运行时从能够弱地存储对象)它将对象存储为非弱置零引用。这意味着观察者不需要在他们的解除分配方法中取消注册。

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

回答by Pablo Ruan

You can use three methods:

您可以使用三种方法:

  1. after popViewController, back navigationControlleror dismissViewControllerAnimated:

    deinit {
        print("Remove NotificationCenter Deinit")
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }
    
  2. viewDidDisappear, remove after it is already the next view controller:

    override func viewDidDisappear(animated: Bool) {
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }
    
  3. viewWillDisappear- before opening the next view:

    override func viewWillDisappear(animated: Bool) {
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }
    
  1. 之后popViewController,返回navigationControllerdismissViewControllerAnimated

    deinit {
        print("Remove NotificationCenter Deinit")
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }
    
  2. viewDidDisappear, 在它已经是下一个视图控制器后删除:

    override func viewDidDisappear(animated: Bool) {
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }
    
  3. viewWillDisappear- 在打开下一个视图之前:

    override func viewWillDisappear(animated: Bool) {
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }
    

Swift 3.0 syntax:

Swift 3.0 语法:

NotificationCenter.default.removeObserver(self)

回答by Ashim Dahal

In Swift 4.2, this is one of the way you can remove observer

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

deinit {
    NotificationCenter.default.removeObserver(self, name: Notification.Name.Identifier, object: nil)
}

setup addObserver notification in viewDidLoad class

在 viewDidLoad 类中设置 addObserver 通知

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

回答by pmick

Swift provides a deinit method that is called on instances of classes before they are destroyed.

Swift 提供了一个 deinit 方法,该方法在类的实例被销毁之前被调用。

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Deinitialization.html

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Deinitialization.html

回答by Guy Daher

I also want to point out that you should use this method:

我还想指出你应该使用这个方法:

func addObserver(_ observer: Any, selector aSelector: Selector, name aName: NSNotification.Name?, object anObject: Any?)

Instead of

代替

func addObserver(forName name: NSNotification.Name?, object obj: Any?, queue: OperationQueue?, using block: @escaping (Notification) -> Void) -> NSObjectProtocol

The latter will not remove the observer (Ran into this problem recently). The former will remove the observer if you are using iOS9.

后者不会移除观察者(最近遇到了这个问题)。如果您使用的是 iOS9,前者将删除观察者。

回答by Pawel Molodkin

deinit {
    NotificationCenter.default.removeObserver(self)
}

回答by mayank khare

It is also good if you add your observer in viewWillAppear()and remove them in viewWillDisappear()

如果您将观察者添加viewWillAppear()并删除它们也很好viewWillDisappear()