Почему не удалить Observer из NSNotificationCenter: addObserverForName: usingBlock get called
Я смущен тем, почему наблюдатель никогда не удаляется в следующем коде. В моем представленииDidAppear у меня есть следующее:
-(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];
}];
}
Наблюдатель никогда не удаляется, и оператор выводится каждый раз, когда уведомление отправляется. Кто-нибудь может дать какие-либо рекомендации?
Ответы
Ответ 1
Когда блок вставляется в стек addObserverForName:
, метод еще не вернулся, поэтому gpsObserver равен нулю (в ARC) или мусору /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, чтобы убедиться, что утечки памяти нет (согласно ответу Мэтта). Код не проверен.
Ответ 2
Я нахожу, что на самом деле есть утечка памяти, если наблюдатель не отмечен как __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];
}];