Ответ
Плюсы:
- Гарантированная подписка –
viewDidLoadвызывается один раз за жизненный цикл контроллера, что обеспечивает своевременную регистрацию наблюдателя до появления view на экране. - Централизация логики – код подписки и обработки уведомления находится в одном классе, что упрощает понимание.
Недостатки и риски:
- Утечки памяти – если не отписаться, объект контроллера будет удерживаться
NotificationCenterдаже после его деаллокации, так какNotificationCenter.defaultявляется синглтоном. - Нежелательные колбэки – контроллер может получать и обрабатывать уведомления, когда его view не находится на экране (например, находится в стеке навигации, но скрыт другим контроллером).
- Сложность отладки – при множественных подписках бывает сложно отследить, откуда пришло уведомление и кто на него подписан.
Рекомендуемая практика в UIKit:
class MyViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Подписываемся на уведомление
NotificationCenter.default.addObserver(self,
selector: #selector(handleDataUpdated(_:)),
name: .dataDidUpdateNotification,
object: nil) // object: nil - слушаем от всех отправителей
}
@objc private func handleDataUpdated(_ notification: Notification) {
guard let newData = notification.userInfo?["data"] as? MyDataModel else { return }
// Обновляем UI на главном потоке
DispatchQueue.main.async {
self.updateUI(with: newData)
}
}
// ОБЯЗАТЕЛЬНО отписываемся в deinit
deinit {
NotificationCenter.default.removeObserver(self)
}
}
// Расширение для удобства
extension Notification.Name {
static let dataDidUpdateNotification = Notification.Name("dataDidUpdateNotification")
}
Современная альтернатива (SwiftUI): Использование @EnvironmentObject, @ObservedObject или .onReceive для Publisher, что обеспечивает реактивное связывание данных без ручного управления подписками.