Почему не удаляется Observer из NSNotificationCenter: addObserverForName: usingBlock вызывается - PullRequest
13 голосов
/ 12 декабря 2011

Я запутался, почему наблюдатель никогда не удаляется в следующем коде.В моем 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 ]

30 голосов
/ 12 декабря 2011

Когда блок помещается в стек с помощью 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, чтобы гарантировать отсутствие утечки памяти (согласно ответу Мэтта).Код не проверен.

11 голосов
/ 16 февраля 2012

Я считаю, что на самом деле происходит утечка памяти, если наблюдатель не помечен как __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];
}];
...