2011-04-14 55 views
36

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

+0

你可以举一个这种情况发生的例子,或者为什么这会成为一个问题? – 2011-04-14 06:00:01

回答

64

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

你在这里以非常有趣,非标准的方式使用“观察者”和“目标”。 'addObserver ...'中的“观察者”指示发布通知时将收到消息的对象,而不是指定构成该消息的方法。通知中没有“目标”的概念。你称之为“目标”的东西在文档中被称为“观察者”。 – 2011-04-14 08:05:45

+2

目标变量指示运行时应该在何处查找对象。我将arg名称目标更改为观察者以消除任何潜在的混淆。 – futureelite7 2011-04-14 09:04:59

+0

虽然我的“你无法回答”可能是太过文字(一个对象无法检测到它是观察者),但这个答案充其量只是很差的做法。对于OP来说,更好的建议是使用除用于此用例的发布和观察通知之外的其他实现。如果一个通知只打算让一个观察者使用,那么使用一个委托和协议不仅可以强制执行,而且可以在对象和它的委托之间的关系中明确表示。 – XJones 2016-02-27 22:55:09

18

斯威夫特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) 
    } 
} 

斯威夫特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) 
    } 
} 
+0

你给我添加观察者的例子在swift 3.0中使用这个扩展 – 2018-01-08 06:52:24

1

的Upvoted答案与extension NotificationCenter { ... }并没有为我工作,因为我的应用程序中创建每次发布通知时,都会有一个viewController的新实例(它有一个通知观察者),所以删除一个一个viewController的新实例的观察者显然不工作。 拥有Notification Observers的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) 


} 
+1

更好的addObserver'viewDidAppear'而不是'viewWillAppear'。 – dimpiax 2017-10-12 11:54:01