【问题标题】:NSNotificationCenter RemoveObserver Not Always WorkingNSNotificationCenter RemoveObserver 并不总是工作
【发布时间】:2014-11-11 01:02:54
【问题描述】:

通常我在viewWillAppear 中添加我的观察者并在viewWillDisappear 中删除它们。在这种情况下,即使在视图消失后,我也需要其中一位观察者继续,以便它可以完成一些工作。为了确保观察者只在这个视图中添加一次,我做了以下操作:

-(void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:YES];

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

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


}

我已经对应用程序的其余部分进行了搜索,以确保该观察者未在其他任何地方注册。不幸的是,有时,但并非所有时候,并且没有一致的因素,通知会被触发两次。我还通过断点和 NSLog 确保不会多次调用 postNotifcationName。我无法在 iPhone 上重现,因为问题似乎仅限于 iPad。

在进一步的故障排除中,我检查了该方法是否是从同一个线程调用的(没有理由不会,只是为了检查)。如果我将removeObserver 放入viewWillDisappear,这个问题就会消失,但是,这又不是我需要它工作的方式。

显然,这种情况的观察者被注册了两次,但我找不到原因。正如您从代码中看到的那样,任何时候注册此观察者时,它都会首先被删除。我唯一的另一个想法是self 是否会“损坏”,以至于removeObserver 无法正常运行?

【问题讨论】:

  • 我有更新。我在 removeObserver 行设置了一个断点,以便检查“self”。事实证明,当这个问题发生时,self 与之前的 addObserver 不同。所以不知何故,在某些不可重复的情况下,自我正在改变。如何最好地处理它?
  • 这是非常不安全的做事方式。看来您可能有两个同一个班级的活生生的实例。如果您不再需要它,您应该始终删除观察者,dealloc 方法是正确的地方。另外请注意通知是异步发送的
  • 我同意这里有些奇怪。目前尚不清楚 self 发生了什么以及为什么这种情况只是偶尔发生并且没有规律。我确实根据该线程其他地方的反馈解决了这个问题,但我应该研究这个自我差异问题以及它为什么会发生。

标签: ios objective-c nsnotificationcenter


【解决方案1】:

不要在viewWillAppear: 中添加观察者,而是尝试在viewDidLoad 中添加您希望在视图消失时保留的观察者。然后你可以在你的dealloc 方法中调用你的removeObserver:name:object:

【讨论】:

  • 不幸的是,这不起作用。我发现,使用断点,对 viewDidLoad 和 dealloc 的调用并不总是平衡的。如果不是,则会出现同样的问题。我还应该提到我正在使用 splitviewcontroller。
  • @C6Silver 我也遇到过 dealloc 中的断点不起作用的情况。尝试将NSLogs 放入 dealloc 以查看它是否被调用。
  • 基于应用程序的行为,无论断点还是 NSLog,调用肯定是不平衡的。我评论过的这个线程中的另一种方法对我来说效果最好。谢谢。
【解决方案2】:

当视图显示时添加你的观察者,当视图消失时移除它。

添加:

- (void)viewDidLoad
{
  [[NSNotificationCenter defaultCenter]addObserver:self
                                            selector:@selector(postMessageWithImage:)
                                                name:@"imageSaved"
                                              object:nil];
}

删除:

- (void)postMessageWithImage:(NSNotification*)aNotification
{
  [[NSNotificationCenter defaultCenter]removeObserver:self
                                                   name:@"imageSaved"
                                                 object:nil];
  // here do your job
}

这是完全有效和高效的。

【讨论】:

  • 我不确定您是否阅读了我的问题。我表示我需要观察者在视图消失时继续以完成任务。我已经表示按照您描述的方式进行操作将解决问题,但它会删除我开始尝试做的事情。
  • 好的,您可以在选择器postMessageWithImage 中删除观察者,您就完成了。让我更新我的答案。
  • 实际上,这对我的事业并不完全有效,但你已经让我走上了解决这个问题的道路。确实将删除放在 postMessageWithImage 中是正确的,但我还需要将 addObserver 移动到开始此过程的方法。否则它只会工作一次,直到加载视图。我测试这种方法的时间比我之前需要显示的问题要长得多。它似乎适用于 iPhone 和 iPad。谢谢!
【解决方案3】:

如果您只想执行一次,请将其放在dispatch_once() 调用的谓词中,例如

static dispatch_once_t lock;
dispatch_once(&lock, ^{
    // put your addObserver call here
});

【讨论】:

  • 这也是一个很好的方法,尽管我需要找到一个地方来移动观察者。我认为我在其他答案中采用的路径对我来说更好,但我再次认为这种方法也是可行的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-17
  • 1970-01-01
  • 2012-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多