Наблюдатель iOS NSNotificationCenter не удаляется

У меня есть следующий код в AppDelegate. Цель состоит в том, чтобы создать пару наблюдателей, а затем вызвать некоторый код. Как только этот код завершит его, он отправляет уведомление, и наблюдатель должен удалить обоих наблюдателей и вызвать обработчик завершения.

Моя проблема в том, что кажется, что наблюдатели не удаляются, как я ожидал. Уведомление публикуется, а запись NSLog записывается в консоль, поэтому я знаю, что наблюдатель работает. Однако при втором вызове NSLog вызывается дважды, в третий раз — три раза и т. д.

Я думаю, что это связано с удалением в блоке кода, который выполняется из наблюдателя, однако я не уверен, как я могу это решить (если это действительно проблема).

Может ли кто-нибудь быть так любезен, чтобы объяснить, как я могу этого добиться?

Спасибо.

-(void) application:(UIApplication *)application performFetchWithCompletionHandler:
(void (^)(UIBackgroundFetchResult))completionHandler {

    [[NSNotificationCenter defaultCenter] addObserverForName:@"fetchDidCompleteNewData" object:nil
                                                     queue:nil usingBlock:^(NSNotification *completed) {

                                                         //Remove Observers
                                                         [[NSNotificationCenter defaultCenter] removeObserver:self
                                                                                                         name:@"fetchDidCompleteNewData"
                                                                                                       object:nil];
                                                         [[NSNotificationCenter defaultCenter] removeObserver:self
                                                                                                         name:@"fetchDidCompleteNoData"
                                                                                                       object:nil];


                                                         // Post completion
                                                         completionHandler(UIBackgroundFetchResultNewData);
                                                         NSLog(@"Background fetch completed... New Data");
                                                     }];

    [[NSNotificationCenter defaultCenter] addObserverForName:@"fetchDidCompleteNoData" object:nil
                                                       queue:nil usingBlock:^(NSNotification *completed) {

                                                           //Remove Observers
                                                           [[NSNotificationCenter defaultCenter] removeObserver:self
                                                                                                           name:@"fetchDidCompleteNoData"
                                                                                                         object:nil];

                                                           [[NSNotificationCenter defaultCenter] removeObserver:self
                                                                                                           name:@"fetchDidCompleteNewData"
                                                                                                         object:nil];

                                                           //post completion
                                                           completionHandler(UIBackgroundFetchResultNoData);
                                                           NSLog(@"Background fetch completed... No New Data");

                                                       }];

    GetDetails *getDetails = [[GetDetails alloc] init];
    [getDetails backgroundRefresh];

}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];

    return YES;
}

person NeilMortonNet    schedule 04.05.2014    source источник


Ответы (2)


Вы не регистрируете self как объект. Более того, когда блок помещается в стек с помощью addObserverForName:, метод еще не вернулся, поэтому notification равно nil.

Создайте глобальный объект, используя block, например

__block __weak id notification;

тогда,

notification =  [[NSNotificationCenter defaultCenter] addObserverForName:@"fetchDidCompleteNewData" object:nil queue:nil usingBlock:^(NSNotification *completed) {

   //Remove Observers
   [[NSNotificationCenter defaultCenter] removeObserver:notification];
}];
person Himanshu Joshi    schedule 04.05.2014
comment
Перевод: при использовании addObserverForName self не является наблюдателем, поэтому вызовы [center removeObserver:self ...] не работают. Наблюдатель — это объект, возвращаемый из addObserverForName, — это наблюдатель, и вы должны его использовать, однако это сложно, потому что его значение еще недоступно, когда блок определен и передан в метод. Объявите переменную, в которой вы сохраняете результат наблюдения, используя __block. - person Pierre Houston; 15.03.2017

Я думаю, что это связано с удалением в блоке кода, который выполняется из наблюдателя, однако я не уверен, как я могу это решить (если это действительно проблема).

Может ли кто-нибудь быть так любезен, чтобы объяснить, как я могу этого добиться?

Конечно.

Вы можете легко проверить свою теорию, не используя метод addObserverForName:object:queue:usingBlock:, а вместо этого используя метод addObserver:selector:name:object:, где selector — это имя функции, которую вы вызываете вместо использования блока.

Просто используйте Руководство по API для NSNotificationCenter для получения подробной информации об этих методах или в целом, поскольку ваш вопрос касался того, какой другой метод вы могли бы использовать, который не требует block, обращение к API — это первое место, где можно проверить наличие альтернативных инструментов в классе.

person John Vitornio    schedule 04.05.2014
comment
Спасибо за ваши Коментарии. Очень признателен. - person NeilMortonNet; 05.05.2014