我有NSNotification
的观察者,被叫两次。我不知道该怎么做。
我用谷歌搜索但没有找到解决方案。
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(connectedToServer:) name:@"ConnectedToServer" object:nil];
- (void)connectedToServer:(NSNotification*)notification {
[[NSNotificationCenter defaultCenter] postNotificationName:@"SendMessageToServer" object:message];
}
答案 0 :(得分:124)
解决方案1:首先要检查通知本身是否发布了两次。
解决方案2:即使通知仅发布一次,也会在您添加通知观察者的次数中调用操作(无论是通知是否相同)。例如,以下两行将为同一通知(self
)注册观察者(aSelector
)两次。
[[NSNotificationCenter defaultCenter] addObserver:self selector:aSelector name:aName object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:aSelector name:aName object:nil];
您必须找到第二次添加观察者的位置,然后将其删除。并且还要确保添加观察者的代码不会被调用两次。
解决方案3:如果您不确定是否已添加观察者,则只需执行以下操作即可。这将确保观察者只被添加一次。
[[NSNotificationCenter defaultCenter] removeObserver:self name:aName object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:aSelector name:aName object:nil];
答案 1 :(得分:15)
如果多次运行addObserver
方法,它将创建多个观察者。我的问题是,我以某种方式将我的观察者放在viewWillAppear
中,在我发布通知之前多次出现,导致我的观察者多次被调用。
虽然EmptyStack的第3个解决方案有效,但是你的观察者被调用两次是有原因的,所以通过找到它,你可以防止不必要的代码行,而不是删除和添加相同的观察者。
我建议将观察者放在viewDidLoad
中,以避免像我经历过的那样简单的错误。
答案 2 :(得分:7)
尝试在viewWillDisappear方法中删除Observer:
-(void)viewWillDisappear:(BOOL)animated{
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"startAnimating" object:nil]; }
答案 3 :(得分:2)
尝试在[[NSNotificationCenter defaultCenter] addObserver:self selector:aSelector name:aName object:nil];
上设置一个断点,并检查它是否被多次调用。
答案 4 :(得分:2)
对于那些在Swift 2.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)
}
}
您可以按如下方式调用此方法:
NSNotificationCenter.defaultCenter().setObserver(self, selector: #selector(methodName), name: "name", object: nil)
扩展将处理先前观察者的删除(如果存在)。即使之前没有观察者存在,此代码也不会崩溃。
答案 5 :(得分:0)
我有两个相同类的实例,花了一些时间才意识到该通知不是在该类的一个实例中运行两次,而是在两个实例中运行两次。
答案 6 :(得分:0)
我在基于文档的应用程序中使用通知。每个文档的观察者类(一个ViewController)都捕获了该通知。打开两个文件,函数被调用了两次。打开了三个文档...您可以轻松解决问题。
要限制接收通知的人,可以指定您对特定对象感兴趣,但这有一个不同之处:该对象必须是类对象的同一实例;您不能简单地比较一个值;因此未匹配UUID,而是
的一个实例class DocumentID {
var id = UUID()
}
工作正常。将其从您的文档插入到发送或接收通知的每个类中,并且对文档的通知受到限制。
答案 7 :(得分:0)
Swift 5+ 解决方案
NotificationCenter.default.removeObserver(self, name: aName, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(aSelector), name: aName, object: nil)
一些提示(一些提示总是意味着 2):
Selector 方法必须暴露给@objc 才能工作,所以按照我们的例子:
@objc func aSelector() { //do work here }
我将通知放在 init()
和 deinit()
中并使用单例来避免重复它们,如下所示:
init() {
NotificationCenter.default.addObserver(self, selector: #selector(aSelector), name: aName, object: nil)
//add any other notifications here
}
deinit() {
NotificationCenter.default.removeObserver(self)
}
答案 8 :(得分:0)
在我的情况下,Notification
正在调用 次数 我出现在同一屏幕上并导致触发 相同的操作 X numberofTime 我进入屏幕。因此,我删除了 Notification
中的 viewWillDisappear
观察者,这实际上是有效的,并且在同一屏幕中停止了多次触发的操作/方法。 >
感谢 Himanth 的回答,我已经想通了
addObserver
override func viewDidLoad(){
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(self.yourNotificationAction(notification:)), name: Notification.Name("yourNotificationName"), object: nil)
}
<块引用>
removeObserver
屏幕消失时
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self, name: Notification.Name("yourNotificationName"), object: nil)
}