43

现在,API 似乎没有提供一种方法来检测是否已经为特定的 NSNotification 添加了观察者。避免添加多个 NSNotification 观察者的最佳方法是在您的末端维护一个标志以进行跟踪之外的最佳方法是什么?有没有人已经创建了一个类别来促进这一点?

4

5 回答 5

72

防止添加重复观察者的一种方法是在再次添加之前为目标/选择器显式调用 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

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

于 2011-04-14T07:51:00.447 回答
19

斯威夫特 5:

import Foundation

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

斯威夫特 3-4:

import Foundation

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

斯威夫特 2:

import Foundation

extension NSNotificationCenter {
  func setObserver(observer: AnyObject, selector: Selector, name: String?, object: AnyObject?) {
    removeObserver(observer, name: name, object: object)
    addObserver(observer, selector: selector, name: name, object: object)
  }
}
于 2015-03-17T12:26:47.843 回答
5

Upvoted 的答案extension NotificationCenter { ... }对我不起作用,因为每次发布通知时我的应用程序都会创建一个新的 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)


}
于 2017-09-27T12:33:40.843 回答
1

那么应该检查苹果文档。
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!")
}
于 2021-06-03T23:10:55.723 回答
0

斯威夫特 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)
    }
}
于 2021-08-01T14:08:24.683 回答