Предупреждение для пользователей iOS / iPhone о повторяющихся наблюдениях NSNotification

Это не столько вопрос, сколько предупреждение для других, чтобы сэкономить время.

NSNotificationCenter на iOS 3 / iPhone OS 3 (я предполагаю, также Mac OS X и iOS 4) имеет следующее поведение:

Если вы зарегистрируетесь несколько раз для получения конкретного уведомления, NSNotificationCenter НЕ распознает избыточность и вместо этого отправит вам столько уведомлений, сколько вы зарегистрировали для наблюдения.

Это почти никогда не бывает тем поведением, которое вы хотите видеть, и почти всегда бывает случайным.

Пример:

Я хочу, чтобы мой контроллер представления получал уведомления от одноэлементного сетевого объекта при поступлении новых данных:

- (void) viewDidLoad 
{
    [super viewDidLoad];

    [[NSNotificationCenter defaultCenter] addObserver:self
            selector:@selector(newDataArrived:) 
                name:NewDataArrivedNotification
              object:[NetworkListener sharedNetworkListener]];
}

но раньше я уже вставлял то же самое в viewWillAppear:

- (void) viewWillAppear
{
    [super viewWillAppear];

    [[NSNotificationCenter defaultCenter] addObserver:self
            selector:@selector(newDataArrived:)
                name:NewDataArrivedNotification
              object:[NetworkListener sharedNetworkListener]];
}

Обратите внимание, что это точно одно и то же уведомление, относящееся к одному и тому же наблюдателю, отправителю и имени уведомления.

В этом случае, если я не удалю один из этих вызовов addObserver, я получу дублирующиеся уведомления на свой контроллер представления.

В многопоточной среде это мир боли. Поверьте мне.

Просто выложите это на случай, если есть другие, которые столкнутся с чем-то вроде этого.


person God of Biscuits    schedule 18.06.2010    source источник
comment
Хорошо, что вы получили предупреждение - вам, вероятно, следует поместить большую часть этого в ответ и принять его :) (сигнал Алекс Требек, бормочущий что-то вроде «должен сформулировать свой ответ…»)   -  person Scott Corscadden    schedule 25.03.2012
comment
Потребовалось у меня достаточно времени, но готово.   -  person God of Biscuits    schedule 21.04.2013


Ответы (3)


NSNotificationCenter на iOS 3 / iPhone OS 3 (я предполагаю, также Mac OS X и iOS 4) имеет следующее поведение:

Если вы зарегистрируетесь несколько раз для получения конкретного уведомления, NSNotificationCenter НЕ распознает избыточность и вместо этого отправит вам столько уведомлений, сколько вы зарегистрировали для наблюдения.

Это почти никогда не бывает тем поведением, которое вы хотите видеть, и почти всегда бывает случайным.

Пример:

Я хочу, чтобы мой контроллер представления получал уведомления от одноэлементного сетевого объекта при поступлении новых данных:

- (void) viewDidLoad 
{
    [super viewDidLoad];

    [[NSNotificationCenter defaultCenter] addObserver:self
            selector:@selector(newDataArrived:) 
                name:NewDataArrivedNotification
              object:[NetworkListener sharedNetworkListener]];
}

но раньше я уже вставлял то же самое в viewWillAppear:

- (void) viewWillAppear
{
    [super viewWillAppear];

    [[NSNotificationCenter defaultCenter] addObserver:self
            selector:@selector(newDataArrived:)
                name:NewDataArrivedNotification
              object:[NetworkListener sharedNetworkListener]];
}

Обратите внимание, что это точно одно и то же уведомление, относящееся к одному и тому же наблюдателю, отправителю и имени уведомления.

В этом случае, если я не удалю один из этих вызовов addObserver, я получу дублирующиеся уведомления на свой контроллер представления.

В многопоточной среде это мир боли. Поверьте мне.

Просто выложите это на случай, если есть другие, которые столкнутся с чем-то вроде этого.

person God of Biscuits    schedule 21.04.2013
comment
Это ошибка кодировщика, а не ошибка библиотеки. Зарегистрируйтесь только для получения уведомлений, которые хотите получать. Я не уверен, зачем вам регистрироваться в одном и том же объекте несколько раз для одного и того же уведомления. - person chadbag; 08.12.2014
comment
в ситуациях, когда у вас есть базовый контроллер представления, который имеет наблюдателя, а некоторые другие контроллеры представления расширяют этот базовый класс, тогда, если код для добавления наблюдателя находится в методах жизненного цикла представления, таких как viewDidLoad или viewDidAppear, способ избежать добавления наблюдателей в Таблицу рассылки удаляется путем удаления наблюдателя и последующего добавления его в поле зрения, которое загружено. Таким образом, наблюдатель не будет добавлен несколько раз. - person Dhiraj Das; 15.05.2017

Вы должны и всегда должны убирать своих наблюдателей.
Самый простой способ сделать это: [[NSNotificationCenter defaultCenter] removeObserver: self]
viewDidLoad не лучшее место для добавления наблюдателей, потому что эти функции могут вызываться несколько раз, это происходит при срабатывании viewDidUnload. . Хорошее место для размещения ваших addObservers в viewWillAppear и removeObservers в viewWillDisappear.

person jakerz    schedule 24.01.2013
comment
Кроме того, viewDidUnload устарел и больше не вызывается в iOS 6. - person God of Biscuits; 21.04.2013

Как вы сами сказали, NSNotificationCenter не проверяет дубликаты, что может раздражать некоторых, но имеет смысл при рассмотрении всей системы, стоящей за ним.

Та же самая логика применима к добавлению целей к определенным объектам, но часто их можно распознать.

Спасибо за понимание и за хорошее SEO-ориентированное предупреждение :)

person Nils Munch    schedule 29.12.2012
comment
Рассмотрим всю систему, стоящую за этим, имеет смысл? Не могли бы вы рассказать поподробнее? Спасибо. - person Jason Lee; 14.05.2013