【问题标题】:Warning for iOS/iPhone users about duplicate NSNotification observationsiOS/iPhone 用户关于重复 NSNotification 观察的警告
【发布时间】:2011-03-05 14:35:44
【问题描述】:

这与其说是一个问题,不如说是在警告其他人以节省一些时间。

iOS 3/iPhone OS 3(我假设 Mac OS X 和 iOS 4)上的 NSNotificationCenter 具有以下行为:

如果您多次为确切的特定通知注册自己,NSNotificationCenter 将识别冗余,而是会向您发出与您注册观察一样多的通知。

这几乎不是你想看到的行为,而且几乎总是偶然的。

例子:

我希望我的视图控制器在新数据进入时接收来自单例网络对象的通知:

- (void) viewDidLoad 
{
    [super viewDidLoad];

    [[NSNotificationCenter defaultCenter] addObserver:self
            selector:@selector(newDataArrived:) 
                name:NewDataArrivedNotification
              object:[NetworkListener sharedNetworkListener]];
}

但之前我已经在 viewWillAppear 中放入了相同的内容:

- (void) viewWillAppear
{
    [super viewWillAppear];

    [[NSNotificationCenter defaultCenter] addObserver:self
            selector:@selector(newDataArrived:)
                name:NewDataArrivedNotification
              object:[NetworkListener sharedNetworkListener]];
}

请注意,它是完全相同相同的通知,解析为相同的观察者、发送者和通知名称。

在这种情况下,如果我不删除其中一个 addObserver 调用,我将收到重复通知到我的视图控制器。

在多线程环境中,这是一个充满伤害的世界。相信我。

只是把它放在那里,以防其他人遇到这样的事情。

【问题讨论】:

  • 很高兴收到警告 - 您可能应该将大部分内容放在答案中并接受它:)(提示 Alex Trebek 喃喃自语“必须说出你的答案……”)
  • 花了我足够长的时间,但完成了。

标签: iphone ios macos nsnotificationcenter nsnotifications


【解决方案1】:

iOS 3/iPhone OS 3(我假设 Mac OS X 和 iOS 4)上的 NSNotificationCenter 具有以下行为:

如果您多次为确切的特定通知注册自己,NSNotificationCenter 将识别冗余,而是会向您发出与您注册观察一样多的通知。

这几乎不是你想看到的行为,而且几乎总是偶然的。

例子:

我希望我的视图控制器在新数据进入时接收来自单例网络对象的通知:

- (void) viewDidLoad 
{
    [super viewDidLoad];

    [[NSNotificationCenter defaultCenter] addObserver:self
            selector:@selector(newDataArrived:) 
                name:NewDataArrivedNotification
              object:[NetworkListener sharedNetworkListener]];
}

但之前我已经在viewWillAppear 中放入了相同的内容:

- (void) viewWillAppear
{
    [super viewWillAppear];

    [[NSNotificationCenter defaultCenter] addObserver:self
            selector:@selector(newDataArrived:)
                name:NewDataArrivedNotification
              object:[NetworkListener sharedNetworkListener]];
}

请注意,它是完全相同相同的通知,解析为相同的观察者、发送者和通知名称。

在这种情况下,如果我不删除其中一个 addObserver 调用,我将收到重复通知到我的视图控制器。

在多线程环境中,这是一个充满伤害的世界。相信我。

只是把它放在那里,以防其他人遇到这样的事情。

【讨论】:

  • 这是编码器错误,而不是库错误。仅注册您想要接收的通知。我不知道你为什么要在同一个对象中多次注册同一个通知。
  • 如果你有一个基础视图控制器,它有一个观察者,而其他一些视图控制器扩展了这个基类,那么如果添加观察者的代码在视图生命周期方法中,比如 viewDidLoad 或 viewDidAppear,避免将观察者添加到调度表的一种方法是删除观察者,然后将其添加到视图中确实加载。这样就不会多次添加观察者了。
【解决方案2】:

你应该并且总是清理你的观察者。
最简单的方法是:[[NSNotificationCenter defaultCenter] removeObserver:self]
viewDidLoad 不是添加观察者的好地方,因为这个函数可能会被多次调用,当 viewDidUnload 被触发时会发生这种情况。 将 addObservers 放入 viewWillAppear 并将 removeObservers 放入 viewWillDisappear 的好地方。

【讨论】:

  • 另外,viewDidUnload 已被弃用,甚至不再在 iOS 6 中调用
【解决方案3】:

正如您自己所说,NSNotificationCenter 不检查重复项,这可能会让某些人感到烦恼,但在考虑其背后的完整系统时才有意义。

相同的逻辑适用于向某些对象添加目标,但通常对这些对象进行关键识别。

感谢您的洞察力,以及对 SEO 友好的良好警告 :)

【讨论】:

  • 考虑一下它背后的完整系统,有意义吗?你能告诉更多的细节吗?谢谢。
猜你喜欢
  • 2015-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-09
相关资源
最近更新 更多