У меня есть случай, когда дочернее представление отправляет уведомление своему родительскому представлению. Теперь я звоню 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, а правильная позиция для отмены регистрации для тех же уведомлений - метод dealloc.
Ты прав. Этот пост очень старый, поэтому не обращайте на него внимания. Важно сбалансировать регистрацию и отменить регистрацию звонков. Либо используйте viewDidLoad и viewDidUnload, либо viewDidLoad (с флагом) и dealloc, либо init и dealloc для регистрации и отмены регистрации ваших уведомлений. См. Комментарий Бена Готлиба для получения соответствующей информации.
Не знаю, правильно ли это, но я делаю по-твоему. И помните, что viewDidUnload устарел с iOS 6.0 ...
На самом деле это плохая идея. Когда память становится низкой, вашему контроллеру представления может быть отправлено предупреждение о памяти. Поведение по умолчанию в этом случае - очистить ваш вид (если вы в данный момент не на экране). В этом случае вы можете получить сообщение viewDidLoad, отправленное второй раз (после события памяти, когда ваше представление возвращается на экран его контроллером навигации). Таким образом, у вас будет две регистрации одного и того же объекта, но только одно удаление. (в его освобождении)
Лучшее решение - либо установить флаг, говорящий о том, что вы зарегистрировались, либо зарегистрироваться в вашем методе инициализации.
правда ли, что dealloc не всегда вызывается? Было бы безопаснее вызвать addObserver в init и вызвать removeObserver в viewDidUnload - или эта схема заставила бы мой контроллер представления не перерегистрироваться после того, как он снова загружается после предупреждения памяти (что привело к выгрузке представления, поскольку оно не было показано )?
По-прежнему не ясно, где разместить removeObserver в этом случае.
Не лучше ли добавитьObserver в ViewWillAppear, а removeObserver в ViewWillDisappear? Таким образом, наблюдатель будет рядом только до тех пор, пока это необходимо. И вызовы добавления / удаления всегда будут сбалансированы, AFAIK.
Я предполагаю, что вероятность «нехватки памяти» в 2017 году очень мала. Так что это не должно быть проблемой. Однако что, если init был слишком ранним, т.е. вы хотели наблюдать за чем-то связанным с пользовательским интерфейсом, и вам нужно, чтобы ваше представление было загружено?
Бен прав - но я нашел другой, потенциально хрупкий способ обойти это. Я обнаружил это только потому, что постоянно получал сообщение «... было освобождено, пока наблюдатели ключевых значений все еще были зарегистрированы с ним»
Я не знаю почему - но когда у меня был addObserver в моем методе инициализации и removeObserver в моем методе dealloc, я все еще получал сообщение о том, что KVO все еще наблюдается. Я прошел и убедился, что мой removeObserver вызывается правильно.
Вместо этого я переместил свой addobserver в метод viewDidLoad, и это, похоже, сработало.
Я оставил removeObserver в viewDidUnload а также в dealloc; но мне это не нравится, потому что это не сбалансировано. Но при нормальных обстоятельствах мой viewDidUnload не вызывается - это просто защита на случай, если я получу уведомление о нехватке памяти.
Но я вижу потенциально попадание в ситуацию, когда возникает событие нехватки памяти, вызывается viewDidUnload. Если через некоторое время после этого я нажму dealloc (до того, как снова нажму viewDidLoad), я дважды вызову removeObserver!
Итак, я думаю, что я просто сохраню его в моем viewDidLoad и моем dealloc.
Я до сих пор не знаю, почему это не работает, если я использую addobserver в своем методе инициализации.
Но при получении предупреждения о памяти, viewDidUnload будет вызываться, но не будет освобожден, при переходе к этому контроллеру представления viewDidLoad будет вызван снова, а затем ваше уведомление снова зарегистрируется.