Подтвердить что ты не робот

Удаляет ли NSNotificationCenterObserver: отменяет регистрацию VC от получения уведомлений о предупреждении памяти?

Я просто наткнулся на проблему в своем приложении: я протестировал вызовы didReceiveMemoryWarning на UIViewController, включая последующие вызовы для viewDidUnload.

Это хорошо работало в старых версиях моего приложения, но теперь не работало в iPhone Simulator: didReceiveMemoryWarning больше не вызывался.

Это вызвано вызовом [NSNotificationCenter defaultCenter] removeObserver:self] в viewWillDisappear (сам являющийся UIViewController), чтобы отменить регистрацию для некоторых уведомлений о жизненном цикле, которые я добавил в viewDidAppear.

Этот глобальный вызов removeObserver: не только удалил мои добавленные уведомления, но, видимо, также уведомление системы UIApplicationDidReceiveMemoryWarningNotification вызвало вызов UIViewController didReceiveMemoryWarning.

Это поведение по дизайну? Я не мог найти ссылку/документ, который указывал, что вызов removeObserver: внутри UIViewController нарушает стандартную обработку памяти.

4b9b3361

Ответ 1

Да, это по дизайну.

Такое поведение меня совсем не удивляет. Реализация UIViewController непрозрачна, поэтому нет возможности точно знать, что она регистрирует экземпляры для UIApplicationDidReceiveMemoryWarningNotification с помощью действия didReceiveMemoryWarning, но это, безусловно, имеет смысл.

Как правило, это плохая практика использовать [[NSNotificationCenter defaultCenter] removeObserver:self] где угодно, но в dealloc. Это связано с тем, что, как вы обнаружили, могут быть непредсказуемые побочные эффекты в реализациях суперкласса. Это более предсказуемо и проще отлаживать/поддерживать ваш код, если вы следуете за соглашением о регистрации только для определенных уведомлений, которые вы зарегистрировали.

Ответ 2

[NSNotificationCenter defaultCenter] removeObserver:observer] отменяет регистрацию observer для всех уведомлений, для которых она ранее была зарегистрирована (включая системные уведомления). Вы можете использовать метод removeObserver:name:object: для отмены подписки на одно уведомление.