【问题标题】:Why doesn't Remove Observer from NSNotificationCenter:addObserverForName:usingBlock get called为什么不从 NSNotificationCenter 删除观察者:addObserverForName:usingBlock 被调用
【发布时间】:2011-12-12 16:41:52
【问题描述】:

我对为什么在以下代码中从未删除观察者感到困惑。在我的 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];

        }];

}

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

【问题讨论】:

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


    【解决方案1】:

    当块被addObserverForName: 压入堆栈时,该方法尚未返回,因此 gpsObserver 为 nil(在 ARC 下)或垃圾/未定义(不在 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 以确保没有内存泄漏(根据马特的回答)。代码未测试。

    【讨论】:

    • 这很有意义并且按预期工作;谢谢你的帮助。
    【解决方案2】:

    我发现实际上存在内存泄漏,除非观察者同时标记为__block__weak。使用 Instruments 确保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];
    }];
    

    【讨论】:

    • 如果他们能引入等效的方法,实际上不需要您坚持观察者而是将自己作为一个整体,只需使用块而不是选择器,我会很高兴。
    • 如果在将NSNotificationCenter 删除后将其设置为nil,则无需创建observer __weak。我已经用 Instruments 进行了检查。
    猜你喜欢
    • 2014-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多