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