Ответ
Стратегия зависит от необходимости уведомлений:
1. Подписка на постоянные уведомления (нужны, пока контроллер жив)
- Подписка:
viewDidLoad() - Отписка:
deinit
// viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(
self,
selector: #selector(handleDataUpdate),
name: .dataDidUpdateNotification,
object: nil
)
}
// deinit
deinit {
// Обязательная отписка для предотвращения утечек памяти
NotificationCenter.default.removeObserver(self)
}
2. Подписка на временные уведомления (нужны только когда экран видим)
- Подписка:
viewWillAppear(_:) - Отписка:
viewWillDisappear(_:)
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(
self,
selector: #selector(handleAppBecameActive),
name: UIApplication.didBecomeActiveNotification,
object: nil
)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self, name: UIApplication.didBecomeActiveNotification, object: nil)
}
Best Practices:
- Всегда отписывайтесь. Неотписанный наблюдатель удерживает контроллер в памяти.
- В iOS 9+ и с использованием блоков отписываться явно не нужно, если использовать возвращаемый токен и хранить его в свойстве (он автоматически отпишется при деинициализации).
- Для отписки от конкретного уведомления используйте
removeObserver(_:name:object:)— это точнее, чемremoveObserver(_:).
Ответ 18+ 🔞
Эй, а вот это, блядь, интересный вопрос! Сидишь ты такой, пишешь приложение, и тут бац — надо ловить эти ваши нотификации. А где их ловить-то, сука? И главное — где отпускать, чтобы память не текла, как решето? Сейчас разжуём, блядь.
Вот смотри, стратегия-то зависит от того, насколько долго тебе эти уведомления нужны. Как будто ты в кино: если фильм на весь сеанс — сиди с начала до конца. А если вышел в туалет — зачем тебе звук из зала? Вернулся — опять подписался. Вот и тут так же.
1. Подписка на постоянные уведомления (нужны, пока контроллер жив, как таракан в щели)
- Где вешаем уши:
viewDidLoad()— как только контроллер загрузился, сразу слушаем. - Где снимаем уши:
deinit— когда контроллер накрывается медным тазом, надо всё отцепить, а то память потечёт, пиздец.
// viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(
self,
selector: #selector(handleDataUpdate),
name: .dataDidUpdateNotification,
object: nil
)
}
// deinit
deinit {
// Это, блядь, ОБЯЗАТЕЛЬНО! Иначе твой контроллер будет висеть в памяти, как призрак, и сосать ресурсы. Отписываемся нахуй.
NotificationCenter.default.removeObserver(self)
}
2. Подписка на временные уведомления (нужны только когда экран торчит перед глазами)
- Где вешаем уши:
viewWillAppear(_:)— вот-вот появимся на экране, пора слушать. - Где снимаем уши:
viewWillDisappear(_:)— только собрались свалить — сразу отписались, чтобы не слушать за спиной, как идиоты.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(
self,
selector: #selector(handleAppBecameActive),
name: UIApplication.didBecomeActiveNotification,
object: nil
)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// Отписываемся только от конкретного уведомления, а не ото всех, как слоупоки.
NotificationCenter.default.removeObserver(self, name: UIApplication.didBecomeActiveNotification, object: nil)
}
Лайфхаки, блядь, чтобы не обосраться:
- Отписывайся всегда, ёпта. Забыл отписаться — получил утечку памяти. Твой контроллер будет жить вечно в аду, и сборщик мусора его не возьмёт.
- Если ты не лох и пишешь под iOS 9+, да ещё и с блоками, то можно по-хитрому: сохранить токен, который
addObserverвозвращает, в свойство. Когда контроллер сдохнет — токен умрёт вместе с ним и всё само отпишется. Красота, блядь! - Не дрочи
removeObserver(_:)на всё подряд. Лучше тыкать в конкретное уведомление черезremoveObserver(_:name:object:)— так точнее, и меньше шансов, что ты случайно отпишешься от чего-то ещё, что тебе нужно.