如何避免添加多个NSNotification观察者?

时间:2011-04-14 04:09:08

标签: cocoa ios

现在,API似乎没有提供检测是否已为特定NSNotification添加观察者的方法。什么是避免添加多个NSNotification观察者的最佳方法,而不是在你的头上保持一个标志以跟踪?有没有人已经创建了一个类别来促进这个?

5 个答案:

答案 0 :(得分:69)

防止添加重复观察者的一种方法是在再次添加目标/选择器之前显式调用removeObserver。我想你可以把它添加为一个类别方法:

@interface NSNotificationCenter (UniqueNotif)

- (void)addUniqueObserver:(id)observer selector:(SEL)selector name:(NSString *)name object:(id)object {

        [[NSNotificationCenter defaultCenter] removeObserver:observer name:name object:object];
        [[NSNotificationCenter defaultCenter] addObserver:observer selector:selector name:name object:object];

}

@end

这假设您只为每个目标添加一个唯一的观察者以获取任何通知名称,因为它将删除该通知名称的所有现有观察者。

答案 1 :(得分:19)

斯威夫特3,4:

import Foundation

extension NotificationCenter {
    func setObserver(_ observer: AnyObject, selector: Selector, name: NSNotification.Name, object: AnyObject?) {
        NotificationCenter.default.removeObserver(observer, name: name, object: object)
        NotificationCenter.default.addObserver(observer, selector: selector, name: name, object: object)
    }
}

Swift 2:

import Foundation

extension NSNotificationCenter {
    func setObserver(observer: AnyObject, selector: Selector, name: String?, object: AnyObject?) {
        NSNotificationCenter.defaultCenter().removeObserver(observer, name: name, object: object)
        NSNotificationCenter.defaultCenter().addObserver(observer, selector: selector, name: name, object: object)
    }
}

答案 2 :(得分:1)

使用extension NotificationCenter { ... }的Upvoted答案对我不起作用,因为我的应用每次发布通知时都会创建一个viewController的新实例(这有一个Notification观察者),所以删除一个新的观察者viewController的实例显然不起作用。 调用具有通知观察者的viewController的先前实例。

以下对我有用,因为一旦视图消失,这就会删除通知观察者。

// Notification observer added 

override func viewWillAppear(_ animated: Bool) {

    NotificationCenter.default.addObserver(self, selector: #selector(self.someFunc(notification:)), name: Notification.Name("myNotification"), object: nil)


}


// Notification observer removed 

override func viewWillDisappear(_ animated: Bool) {

    NotificationCenter.default.removeObserver(self, name: Notification.Name("myNotification"), object: nil)


}

答案 3 :(得分:0)

好吧,应该检查一下苹果文档。
https://developer.apple.com/documentation/foundation/notificationcenter/1411723-addobserver

let center = NSNotificationCenter.defaultCenter
var tokenOpt: NSObjectProtocol?
tokenOpt = center.addObserverForName("OneTimeNotification", object: nil, queue: nil) { (note) in
    print("Received the notification!")
    center.removeObserver(token!)
}

因此,如果通知已经存在,请确保不会添加通知

if let token = tokenOpt{
  center.removeObserver(token)
}
tokenOpt = center.addObserverForName("OneTimeNotification", object: nil, queue: mainQueue) { (note) in
    print("Received the notification!")
}

答案 4 :(得分:0)

Swift 5:

根据@futureelite7 和@dimpiax 之前的回答对 Swift 5 进行了一些调整

extension NotificationCenter {
    func setObserver(_ observer: AnyObject, selector: Selector, name: NSNotification.Name, object: AnyObject?) {
        NotificationCenter.default.removeObserver(observer,
                                                  name: name,
                                                  object: object)
        NotificationCenter.default.addObserver(observer,
                                               selector: selector,
                                               name: name,
                                               object: object)
    }
}