如何阻止NSNotification中的Observer调用两次?

问题描述 投票:51回答:6

我有一个NSNotification的观察者,被叫两次。我不知道该怎么做。

我用谷歌搜索但没有找到解决方案。

[[NSNotificationCenter defaultCenter] addObserver:self
     selector:@selector(connectedToServer:) name:@"ConnectedToServer" object:nil];

- (void)connectedToServer:(NSNotification*)notification {

    [[NSNotificationCenter defaultCenter] postNotificationName:@"SendMessageToServer" object:message];
}
iphone objective-c ios nsnotifications
6个回答
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];

15
投票

如果你的addObserver方法多次运行,它将创建多个观察者。我的问题是我以某种方式将我的观察者放在viewWillAppear中,它在我发布通知之前多次出现,导致我的观察者被多次调用。

虽然EmptyStack的第3个解决方案有效,但有一个原因是你的观察者被调用两次,所以通过找到它,你可以防止不必要的代码行,而不是删除和添加相同的观察者。

我建议把你的观察者放在viewDidLoad,以避免像我经历的那样的简单错误。


7
投票

尝试在viewWillDisappear方法中删除Observer:

-(void)viewWillDisappear:(BOOL)animated{

[[NSNotificationCenter defaultCenter] removeObserver:self name:@"startAnimating" object:nil]; }

2
投票

尝试在[[NSNotificationCenter defaultCenter] addObserver:self selector:aSelector name:aName object:nil];上设置断点并检查它是否被多次调用。


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)

扩展将处理先前观察者的删除(如果存在)。即使之前没有观察者存在,此代码也不会崩溃。


0
投票

我有两个同一个类的实例,我花了一些时间才意识到通知在该类的一个实例中没有运行两次但在两个实例中运行两次。

© www.soinside.com 2019 - 2024. All rights reserved.