Возможные места для вызова методов addObserver и removeObserver
-
03-07-2019 - |
Вопрос
У меня есть случай, когда дочернее представление отправляет уведомление своему родительскому представлению.Теперь я звоню addObserver:
в viewWillAppear:
и removeObserver:
в viewWillDisappear:
.Но, я предполагаю, что это неверно, поскольку viewWillAppear:
вызывает при обновлении представления.
[[NSNotificationCenter defaultCenter] addObserver: (id)observer selector: (SEL)aSelector name: (NSString *)aName object: (id)anObject];
[[NSNotificationCenter defaultCenter] removeObserver: (id)observer name: (NSString *)aName object: (id)anObject];
Спасибо.
Решение
На самом деле, это плохая идея.Когда памяти становится мало, вашему контроллеру просмотра может быть отправлено предупреждение о нехватке памяти.Поведение по умолчанию в этом случае заключается в очистке вашего представления (если вы в данный момент не находитесь на экране).В этом случае вы могли бы получить сообщение viewDidLoad, отправленное во второй раз (после события memory, когда ваш вид возвращается на экран с помощью навигационного контроллера). Таким образом, у вас будет две регистрации одного и того же объекта, но только одно удаление (в его dealloc)
Лучшим решением является либо установка флага, говорящего о том, что вы зарегистрировались, либо регистрация в вашем методе инициализации.
Другие советы
Я предполагаю, что правильными позициями для регистрации для получения уведомления являются viewDidLoad
метод и правильная позиция для отмены регистрации для тех же уведомлений следующие dealloc
способ.
Бен прав, но я нашел другой, потенциально хрупкий, способ обойти это.Я только что обнаружил это, потому что я постоянно получал сообщение "... был освобожден, в то время как наблюдатели за ключевыми значениями все еще были зарегистрированы с ним".
Я не знаю почему, но когда у меня был addObserver в моем методе init и removeObserver в моем методе dealloc, я все еще получал сообщение о том, что KVO все еще наблюдается.Я прошел через это и убедился, что мой removeObserver вызывается правильно.
Вместо этого я переместил свой addobserver в метод viewDidLoad, и это, похоже, сработало.
Я оставил removeObserver в viewDidUnload и в dealloc;но мне это не нравится, потому что это не сбалансировано.Но при обычных обстоятельствах мой viewDidUnload не вызывается - это просто защита на случай, если я получу уведомление о нехватке памяти.
Но я вижу, что потенциально могу попасть в ситуацию, когда возникает событие нехватки памяти, вызывается viewDidUnload.Если я затем нажму dealloc через некоторое время после этого (прежде чем снова нажму viewDidLoad), я дважды вызову removeObserver!
Так что, я думаю, я просто сохраню это в моем viewDidLoad и моем dealloc.
Я до сих пор не знаю, почему это не работает правильно, если я использую addobserver в своем методе init.