关于cocoa:如何避免添加多个NSNotification观察者?

How to avoid adding multiple NSNotification observer?

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


防止添加重复观察器的一种方法是在再次添加目标/选择器之前显式调用该目标/选择器的removeobserver。我想您可以将此添加为类别方法:

1
2
3
4
5
6
7
8
9
10
@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

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


斯威夫特3, 4:

1
2
3
4
5
6
7
8
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:

1
2
3
4
5
6
7
8
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)
    }
}


由于我的应用程序每次发布通知时都会创建一个新的viewcontroller实例(它有一个通知观察器),所以使用extension NotificationCenter { ... }的投票结果对我来说不起作用,因此删除viewcontroller新实例上的观察器显然不起作用。将调用以前具有通知观察器的ViewController实例。

下面的内容对我很有用,因为这是在视图消失后立即删除通知观察器。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 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)


}