Ios NSNotificationCenter RemoveObserver不总是工作

Ios NSNotificationCenter RemoveObserver不总是工作,ios,objective-c,nsnotificationcenter,Ios,Objective C,Nsnotificationcenter,通常,我会在视图中添加观察者,然后在视图中删除观察者,观察者将消失。在这种情况下,我需要一个观察者在视图消失后继续观察,以便它可以完成一些工作。为了确保使用此视图只添加一次观察者,我执行以下操作: -(void)viewWillAppear:(BOOL)animated { [super viewWillAppear:YES]; [[NSNotificationCenter defaultCenter]removeObserver:self

通常,我会在
视图中添加观察者,然后在
视图中删除观察者,观察者将消失。在这种情况下,我需要一个观察者在视图消失后继续观察,以便它可以完成一些工作。为了确保使用此视图只添加一次观察者,我执行以下操作:

-(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
放在
viewwilldiscover
中,这个问题就会消失,但是,我也不需要这样做


显然,这是一个观察员被登记两次的情况,但我找不到这样做的原因。正如您从代码中看到的,无论何时注册此观察者,它都会首先被删除。我唯一的另一个想法是,
self
是否会“损坏”,从而导致
removeObserver
无法正常工作

不要在
视图中添加观察者将出现:
,当视图在
viewDidLoad
中消失时,尝试添加您希望保留的观察者。然后,您可以在
dealloc
方法中调用您的
removeObserver:name:object:
,在视图显示时添加您的观察者,并在视图消失时将其删除

添加:

- (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
}
删除:

- (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
}

这是非常有效和高效的。

如果您只想执行一次,请将其放在
dispatch\u once()
调用的谓词中,如

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

我不确定你是否读过我的问题。我指出,当视图消失时,我需要观察者继续,以便完成任务。我已经指出,按照您描述的方式进行操作将解决问题,但它会删除我开始尝试执行的操作。好的,您可以删除选择器
postMessageWithImage
中的观察者,您完成了。让我更新我的答案。事实上,这对我的事业并不完全有效,但你让我走上了解决这个问题的道路。确实,将remove放在postMessageWithImage中是正确的,但是我还需要将addObserver移动到启动此过程的方法。否则,在加载视图之前,它只能工作一次,不能再次工作。我对这种方法进行了测试,测试时间比之前的问题显示所需的时间要长得多。它似乎在iPhone和iPad上都能正常工作。非常感谢。不幸的是,这不起作用。使用断点,我发现对viewDidLoad和dealloc的调用并不总是平衡的。如果他们没有,同样的问题也会发生。我还应该提到,我使用的是splitviewcontroller,但我也遇到过dealloc中的断点实际上不起作用的情况。尝试将
NSLog
s放入dealloc以查看它是否被调用。根据应用程序的行为,无论断点或NSLog如何,调用都绝对不平衡。我在这篇文章中评论的另一种方法最适合我。谢谢,我有最新消息。我在removeObserver行中放置了一个断点,以便检查“self”。事实证明,当这个问题发生时,self与前面的addObserver不同。所以,不知何故,在某些不可重复的情况下,自我正在改变。如何最好地处理这个问题?这是一种非常不安全的做事方式。看起来您可能有同一类的两个实例。如果您不再需要observer,您应该始终删除它,dealloc方法是正确的位置。另外请注意,通知是异步发送的。我同意这里有些奇怪。现在还不清楚self到底发生了什么,也不清楚为什么这只是偶然发生的,没有模式。我确实根据这条线索上其他地方的反馈解决了这个问题,但我应该研究一下这个自我差异问题以及它为什么会发生。这也是一个很好的方法,尽管我需要找到一个地方去移动观察者。我认为我在另一个答案中选择的方法对我来说更好,但我再次认为这种方法也是可行的。