为什么不从NSNotificationCenter中删除Observer:addObserverForName:usingBlock get called

war*_*eed 13 iphone nsnotifications nsnotificationcenter ios objective-c-blocks

我很困惑为什么在以下代码中永远不会删除观察者.在我的viewDidAppear中我有以下内容:

-(void)viewDidAppear:(BOOL)animated{

id gpsObserver = [[NSNotificationCenter defaultCenter] 
                          addObserverForName:FI_NOTES[kNotificationsGPSUpdated] 
                          object:nil 
                          queue:[NSOperationQueue mainQueue] 
                          usingBlock:^(NSNotification *note){

                              NSLog(@"run once, and only once!");

                [[NSNotificationCenter defaultCenter] removeObserver:gpsObserver];

        }];

}
Run Code Online (Sandbox Code Playgroud)

永远不会删除观察者,并且每次发送通知时都会输出语句.有人可以提供任何指导吗?

Rob*_*Cat 30

当块被方法推入堆栈时addObserverForName:尚未返回,因此gpsObserver为nil(在ARC下)或garbage/undefined(不在ARC下).使用__block外部声明变量,这应该工作.

__block __weak id gpsObserver;

gpsObserver = [[NSNotificationCenter defaultCenter] 
                          addObserverForName:FI_NOTES[kNotificationsGPSUpdated] 
                          object:nil 
                          queue:[NSOperationQueue mainQueue] 
                          usingBlock:^(NSNotification *note){

                              NSLog(@"run once, and only once!");

                [[NSNotificationCenter defaultCenter] removeObserver:gpsObserver];

        }];
Run Code Online (Sandbox Code Playgroud)

我添加了__weak以确保没有内存泄漏(根据Matt的回答).代码未经测试.


mat*_*att 11

我发现实际上存在内存泄漏,除非观察者被标记为__block__weak.使用仪器确保self不会过度保持; 我敢打赌.但是,这可以正常工作(从我的实际代码):

__block __weak id observer = [[NSNotificationCenter defaultCenter] 
    addObserverForName:@"MyMandelbrotOperationFinished" 
    object:op queue:[NSOperationQueue mainQueue] 
    usingBlock:^(NSNotification *note) {
        // ... do stuff ...
        [[NSNotificationCenter defaultCenter] 
            removeObserver:observer 
            name:@"MyMandelbrotOperationFinished" 
            object:op];
}];
Run Code Online (Sandbox Code Playgroud)

  • 如果从`NSNotificationCenter`中删除它后将它设置为`nil`,则不需要生成`observer`` __ weak`.我用仪器检查了这个. (2认同)