Возможные места для вызова методов addObserver и removeObserver

У меня есть случай, когда дочернее представление отправляет уведомление своему родительскому представлению. Теперь я звоню 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];

Спасибо.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
8
0
7 482
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Я предполагаю, что правильная позиция для регистрации для уведомления - это метод viewDidLoad, а правильная позиция для отмены регистрации для тех же уведомлений - метод dealloc.

Но при получении предупреждения о памяти, viewDidUnload будет вызываться, но не будет освобожден, при переходе к этому контроллеру представления viewDidLoad будет вызван снова, а затем ваше уведомление снова зарегистрируется.

ZYiOS 22.08.2011 06:36

Ты прав. Этот пост очень старый, поэтому не обращайте на него внимания. Важно сбалансировать регистрацию и отменить регистрацию звонков. Либо используйте viewDidLoad и viewDidUnload, либо viewDidLoad (с флагом) и dealloc, либо init и dealloc для регистрации и отмены регистрации ваших уведомлений. См. Комментарий Бена Готлиба для получения соответствующей информации.

Mustafa 22.08.2011 10:16

Не знаю, правильно ли это, но я делаю по-твоему. И помните, что viewDidUnload устарел с iOS 6.0 ...

DanSkeel 25.11.2012 19:50
Ответ принят как подходящий

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

Лучшее решение - либо установить флаг, говорящий о том, что вы зарегистрировались, либо зарегистрироваться в вашем методе инициализации.

правда ли, что dealloc не всегда вызывается? Было бы безопаснее вызвать addObserver в init и вызвать removeObserver в viewDidUnload - или эта схема заставила бы мой контроллер представления не перерегистрироваться после того, как он снова загружается после предупреждения памяти (что привело к выгрузке представления, поскольку оно не было показано )?

matm 03.06.2011 14:26

По-прежнему не ясно, где разместить removeObserver в этом случае.

Resh32 20.09.2012 16:09

Не лучше ли добавитьObserver в ViewWillAppear, а removeObserver в ViewWillDisappear? Таким образом, наблюдатель будет рядом только до тех пор, пока это необходимо. И вызовы добавления / удаления всегда будут сбалансированы, AFAIK.

ToolmakerSteve 07.09.2016 11:29

Я предполагаю, что вероятность «нехватки памяти» в 2017 году очень мала. Так что это не должно быть проблемой. Однако что, если init был слишком ранним, т.е. вы хотели наблюдать за чем-то связанным с пользовательским интерфейсом, и вам нужно, чтобы ваше представление было загружено?

Honey 25.09.2017 04:23

Бен прав - но я нашел другой, потенциально хрупкий способ обойти это. Я обнаружил это только потому, что постоянно получал сообщение «... было освобождено, пока наблюдатели ключевых значений все еще были зарегистрированы с ним»

Я не знаю почему - но когда у меня был addObserver в моем методе инициализации и removeObserver в моем методе dealloc, я все еще получал сообщение о том, что KVO все еще наблюдается. Я прошел и убедился, что мой removeObserver вызывается правильно.

Вместо этого я переместил свой addobserver в метод viewDidLoad, и это, похоже, сработало.

Я оставил removeObserver в viewDidUnload а также в dealloc; но мне это не нравится, потому что это не сбалансировано. Но при нормальных обстоятельствах мой viewDidUnload не вызывается - это просто защита на случай, если я получу уведомление о нехватке памяти.

Но я вижу потенциально попадание в ситуацию, когда возникает событие нехватки памяти, вызывается viewDidUnload. Если через некоторое время после этого я нажму dealloc (до того, как снова нажму viewDidLoad), я дважды вызову removeObserver!

Итак, я думаю, что я просто сохраню его в моем viewDidLoad и моем dealloc.

Я до сих пор не знаю, почему это не работает, если я использую addobserver в своем методе инициализации.

Другие вопросы по теме