目前API似乎没有提供一种方法来检测是否已经为特定的NSNotification添加了观察者。除了在您的端上维护一个标志以进行跟踪之外,避免添加多个NSNotification观察者的最佳方法是什么?是否已经有人创建了一个类别来方便这个操作?
目前API似乎没有提供一种方法来检测是否已经为特定的NSNotification添加了观察者。除了在您的端上维护一个标志以进行跟踪之外,避免添加多个NSNotification观察者的最佳方法是什么?是否已经有人创建了一个类别来方便这个操作?
防止重复添加观察者的一种方法是在再次添加之前明确调用目标/选择器的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
这假设你只会为每个通知名称添加一个唯一的观察者,因为它会删除该通知名称下的任何现有观察者。
addObserver...
中,“observer”表示将在通知发布时接收消息的对象,而不是构成该消息的方法。通知中没有“target”的概念。你所称之为“target”的东西在文档中被称为“observer”。 - jscsimport 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)
}
}
Swift 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)
}
}
Swift 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)
}
}
removeObserver(self, forKeyPath: tag)
?你在哪里找到的? - dimpiax对我来说,带有extension NotificationCenter { ... }
的被点赞的答案并没有起作用,因为每次发布通知时,我的应用程序都会创建一个新的viewController实例(其中包含一个Notification观察者),所以在新的viewController实例上删除观察者显然不起作用。之前具有Notification观察器的viewController实例将被调用。
以下内容适用于我,因为这是在视图消失时立即移除Notification Observer。
// 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)
}
viewDidAppear
中使用更好的addObserver
而不是viewWillAppear
。 - dimpiaxviewWillAppear
中(可能只是为了动画),则必须将其放置在函数 viewDidAppear
中,当视图控制器出现并准备好与用户交互时。 - dimpiax好吧,应该查看苹果文档。
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!")
}
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)
}
}