2012-04-06 3 views
16

Я обычно использую NSNotification как образец ниже:Какой лучший способ, чтобы удалить уведомления наблюдатель

В viewDidLoad:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(foo:) name:kName1 object:nil]; 
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(bar:) name:kName2 object:nil]; 

В viewDidUnload и dealloc:

[[NSNotificationCenter defaultCenter] removeObserver:self]; 

Но другу сказал, что я не должен использовать [[NSNotificationCenter defaultCenter] removeObserver:self];, потому что он удалит всех наблюдателей, включая суперкласс. Он предложил мне использовать следующий код для удаления наблюдателя один за другим.

[[NSNotificationCenter defaultCenter] removeObserver:self name:kName1 object:nil]; 
[[NSNotificationCenter defaultCenter] removeObserver:self name:kName2 object:nil]; 

Я проверил код библиотеки ASIHttpRequest в (https://github.com/pokeb/asi-http-request). Это следует за предложением моих друзей.

Я хочу знать, прав ли мой друг или нет? На мой взгляд, поскольку текущий экземпляр будет выгружен или dealloc, уведомление суперкласса также бесполезно. И есть ли уведомление об использовании подкласса системы UIViewController?

+0

Что это значит, что он удалит «суперклассного наблюдателя»? Наблюдатель - это экземпляр объекта, а не класс. Если он будет освобожден, он должен отменить регистрацию всех уведомлений, даже если они были зарегистрированы в коде суперкласса. – MrTJ

+0

@MrTJ Я имею в виду наблюдателя уведомлений, который добавляется в методе супер. Возможно, отцу экземпляра класса также понадобятся некоторые уведомления при вызове метода viewDidUnload. – tangqiaoboy

+0

Возможно, возможно.Если вы хотите отменить регистрацию в viewDidUnload, тогда для обеспечения безопасности я также предлагаю использовать второй метод (при регистрации пользователя без регистрации) – MrTJ

ответ

12

Ваш друг на 100% правилен. Хотя, не имеет значения, удалите ли вы все уведомления в dealloc.
Вы упомянули viewDidUnload, и там случай совершенно другой, потому что незагруженный объект останется в живых, и вы не знаете, когда снова будут добавлены замечания по надзору над суперклассом. Если они добавлены в viewDidLoad, у вас не будет проблем. Если они добавлены в методе init, вы просто потеряли кучу важных уведомлений.

Удаление наблюдений с конкретными именами является хорошей практикой и должно выполняться с самого начала.

+0

Спасибо. Таким образом, мы можем использовать '[[NSNotificationCenter defaultCenter] removeObserver: self];' в 'dealloc', но НЕ в методе' viewDidUnload', правильно? – tangqiaoboy

+0

Да, 'removeObserver:' не следует использовать за пределами dealloc. Но мне нравится удалять каждое наблюдение специально, поэтому я вообще не использую 'removeObserver:'. Я использую специальный метод 'removeObserver: name: object:' для всех моих уведомлений. Мне очень нравится мой код. –

7

Если вы хотите, чтобы удалить все уведомления вы используете,

[[NSNotificationCenter defaultCenter] removeObserver:self]; 

Если вы хотите удалить конкретное уведомление вы используете,

[[NSNotificationCenter defaultCenter] removeObserver:self name:kName1 object:nil]; 

Когда вы больше не нуждается в каких-либо извещениях первых подход прост.

0

Я использую первый способ, я никогда не думал о том, было ли это правильно или нет. Если вызывается dealloc, тогда объект (супер также) будет все равно освобожден. То, что вы определенно НЕ хотите, это NSNotification, отправляемый на освобожденный экземпляр.

1

Поскольку объект уходит, можно использовать [[NSNotificationCenter defaultCenter] removeObserver:self]; в методе dealloc.

В методе ViewDidUnload вам лучше удалить каждого наблюдателя один за другим, так как ссылка на контроллер по-прежнему находится вокруг (и ваш соответствующий viewDidLoad должен добавить их обратно).

Смежные вопросы