如何阻止 NSNotification 中的 Observer 被调用两次?
我有一个 NSNotification 观察者,它被调用了两次。我不知道该怎么办。
我用谷歌搜索但没有找到解决方案。
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(connectedToServer:) name:@"ConnectedToServer" object:nil];
- (void)connectedToServer:(NSNotification*)notification {
[[NSNotificationCenter defaultCenter] postNotificationName:@"SendMessageToServer" object:message];
}
I have an observer of NSNotification
which is called twice. I do not know what to do with it.
I googled it but no solution found.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(connectedToServer:) name:@"ConnectedToServer" object:nil];
- (void)connectedToServer:(NSNotification*)notification {
[[NSNotificationCenter defaultCenter] postNotificationName:@"SendMessageToServer" object:message];
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
解决方案 1: 首先检查通知本身是否发布了两次。
解决方案 2:即使通知仅发布一次,操作也会被调用,次数与您为通知添加观察者的次数相同(无论通知是否相同)或不)。例如,以下两行将为同一个通知(
aSelector
)注册观察者(self
)两次。您必须找到第二次添加观察者的位置,并将其删除。并且还要确保添加观察者的代码不会被调用两次。
解决方案3:如果您不确定是否已经添加了观察者,您可以简单地执行以下操作。这将确保观察者仅添加一次。
Solution 1: The first thing is to check if the notification itself is posted twice.
Solution 2: Even if the notification is posted only once, the action will be called as many times you've added the observer for the notification (no matter the notification is same or not). For example, the following two lines will register the observer(
self
) for the same notification(aSelector
) twice.You have to find where you are adding observer for the second time, and remove it. And also make sure that the code where you are add the observer is not called twice.
Solution 3: If you are not sure whether you have already added the observer or not, you can simply do the following. This will make sure that the observer is added only once.
如果您的
addObserver
方法运行多次,它将创建多个观察者。我的问题是,我以某种方式将观察者放置在 viewWillAppear 中,在我发布通知之前它出现了多次,并导致我的观察者被多次调用。虽然 EmptyStack 的第三个解决方案有效,但您的观察者被调用两次是有原因的,因此通过找到它,您可以防止不必要的代码行,而不是删除和添加相同的观察者。
我建议将您的观察者放在
viewDidLoad
中,以避免像我遇到的那样的简单错误。If your
addObserver
method is run multiple times, it will create multiple observers. My issue was that I somehow placed my observer inviewWillAppear
which appeared multiple times before I posted the notification and it resulted in my observer being called multiple times.While EmptyStack's 3rd solution works, there is a reason your observer is being called twice, so by finding it, you can prevent needless lines of code instead of removing and adding the same observer.
I would suggest putting your observer in
viewDidLoad
to avoid simple errors like the one I experienced.尝试在 viewWillDisappear 方法中删除Observer:
Try to removeObserver in viewWillDisappear method :
尝试在
[[NSNotificationCenter defaultCenter] addObserver:selfselector:aSelector name:aName object:nil];
上设置断点并检查是否被多次调用。Try set a breakpoint on
[[NSNotificationCenter defaultCenter] addObserver:self selector:aSelector name:aName object:nil];
and check if it is called more than once.对于那些在 Swift 2.2 及更高版本中寻找解决方案并且像我一样遇到这个问题的人,您可以创建一个扩展,如下所示:
您可以按如下方式调用此方法:
该扩展将处理先前观察者(如果存在)的删除。即使之前没有观察者在场,这段代码也不会崩溃。
For those looking for a solution in Swift 2.2 and above and who have reached this question like me you can create an extension as follows :
You can call this method as follows :
The extension will handle the removal of previous observer if it exists. Even if there was no previous observer present this code won't crash.
我有同一个类的两个实例,我花了一些时间才意识到通知不是在该类的一个实例中运行两次,而是在两个实例中运行两次。
I had two instances of the same class and it took me some time before I have realised that the notification is not running twice in one instance of that class but twice in two instances.
我在基于文档的应用程序中使用通知。每个文档的观察者类(ViewController)都会捕获该通知。打开两个文档,函数被调用两次。打开三个文档...您就明白了。
为了限制谁接收通知,您可以指定您对特定对象感兴趣,但这有一个问题:该对象必须是类对象的同一实例;你不能简单地比较一个值;所以 UUID 不匹配,但实例
工作正常。将其从您的文档注入到每个发送或接收通知的类,并且您将限制通知到您的文档。
I use notifications in a document-based app. Every document's observer class (a ViewController) caught the notification. Two documents open, function was called twice. Three documents open... you get the drift.
To limit who receives the notification, you can specify that you're interested in a particular object, but this has a twist: the object needs to be the same instance of a class object; you cannot simply compare a value; so UUID does not get matched, but an instance of
works fine. Inject this from your Document to every class that sends or receives notifications, and you've limited notifications to your document.
Swift 5+ 解决方案
几个提示(几个总是意味着 2):
选择器方法必须暴露给 @objc 才能工作,因此根据我们的示例:
我将通知放在
init()
和deinit()
中,并使用单例来避免重复它们,如下所示:<前><代码>init() {
NotificationCenter.default.addObserver(self, 选择器: #selector(aSelector), 名称: aName, 对象: nil)
//在这里添加任何其他通知
}
去初始化(){
NotificationCenter.default.removeObserver(self)
}
Swift 5+ Solution
A couple of tips (and a couple ALWAYS means 2):
Selector method must be exposed to @objc to work, so per our example:
I put the notifications in the
init()
anddeinit()
and use singletons to avoid repeating them, like this: