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

时间:2011-12-12 16:41:53

标签: iphone ios objective-c-blocks nsnotifications nsnotificationcenter

我很困惑为什么在以下代码中永远不会删除观察者。在我的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];

        }];

}

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

2 个答案:

答案 0 :(得分: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];

        }];

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

答案 1 :(得分: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];
}];