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

Если вы не сделаете этого, а объект прекратит свое существование и будет разослано уведомление, для получения которого этот объект зарегистрирован, то центр уведомлений попытается отправить соответствующее сообщение данному, уже отсутствующему объекту. В итоге произойдет аварийный отказ в лучшем случае, а в худшем — полный хаос.

Для того чтобы снять объект с регистрации на получение уведомлений, достаточно отправить центру уведомлений сообщение removeObserver:. (С другой стороны, объект можно снять с регистрации на получение только отдельных уведомлений с помощью метода removeObserver: name : object:.) В качестве аргумента observer: соответствующему методу передается объект, который уже не принимает уведомления. Каким должен быть этот объект, зависит, прежде всего, от одного из следующих способов регистрации.

Вызов метода addObserver:...................

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

Вызов метода addObserverForName:....

В результате вызова метода addObserverForName: . . . возвращается объект маркера наблюдателя, который сохраняется в переменной id (его класс и характер особого значения не имеют). По существу, это наблюдатель, который требуется снять с регистрации.

Самое главное — найти подходящий момент для снятия с регистрации. В качестве запасного варианта можно воспользоваться методом dealloc зарегистрированного экземпляра. Это последнее событие времени действия, посылаемое экземпляру перед тем, как он прекратит свое существование. Если выбрать второй способ снятия с регистрации, воспользовавшись механизмом ARC и методом addObserverForName: . . ., то следует принять во внимание некоторые дополнительные последствия для управления памятью, о которых речь пойдет в главе 12.

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

экземпляра _observers типа NSMutableSet, то с самого начала она инициализируется пустым множеством, как показано ниже.

 

self->_observers = [NSMutableSet set];

 

Всякий раз, когда регистрация на получение уведомлений производится с помощью блока, результат фиксируется и вводится в множество следующим образом:

id ob = [[NSNotificationCenter defaultCenter]

addObserverForName:©"whatever" object:nil queueinil usingBlock:A(NSNotification *note) {

// ... все, что угодно ...

}];

[self->_observers addObjectiob];

Когда же наступает время для снятия с регистрации, то организуется перечисление элементов множества, как показано ниже.

for (id ob in self->_observers)

[[NSNotificationCenter defaultCenter] removeObserver:ob];

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

 

В классе NSNotif icationCenter никакой интроспекции не предоставляется. В частности, к центру уведомлений типа NSNotif icationCenter нельзя обратиться с запросом, чтобы выяснить, какие именно объекты зарегистрированы в нем в качестве получателей уведомлений. На мой взгляд, это серьезный пробел в функциональных возможностях среды Cocoa. Некогда мне пришлось потратить немало времени, чтобы понять, почему один из экземпляров в коде моего приложения не получал уведомление, на которое он был зарегистрирован. Простейшая самодиагностика кода не помогла. Однако в конечном итоге я понял, что в одном забытом мною фрагменте кода наблюдатель преждевременно снимался с регистрации. Из всего сказанного можно сделать следующий вывод: логика постановки и снятия с регистрации должна быть очень простой.


 

 

 

Добавить комментарий