Логотип YeaHub

База вопросов

Собеседования

Тренажёр

База ресурсов

Обучение

Навыки

Задачи

Войти

Выбери, каким будет IT завтра — вместе c нами!

YeaHub — это полностью открытый проект, призванный объединить и улучшить IT-сферу. Наш исходный код доступен для просмотра на GitHub. Дизайн проекта также открыт для ознакомления в Figma.

© 2026 YeaHub

AI info

Карта сайта

Документы

Медиа

Назад
Вопрос про IOS: subscription, notificationcenter

Почему подписки и отписки на события опасно делать в viewDidLoad?

Вопрос проверяет понимание жизненного цикла, утечек памяти и того, почему “один раз подписался” часто ломает поведение при повторных показах экрана и интерактивных переходах.

Короткий ответ

viewDidLoad вызывается обычно один раз, но экран может появляться и исчезать много раз. Если подписаться в viewDidLoad, события будут приходить даже когда экран не виден, а отписка “в другом месте” легко забудется или не отработает в edge-кейсах. Это приводит к утечкам, дублям обработчиков и багам с состоянием. Подписки обычно привязывают к viewWillAppear/viewDidDisappear или к более явному жизненному циклу объекта.

Длинный ответ

Опасность в том, что viewDidLoad относится к моменту создания view, а подписки относятся к моменту активности экрана. Эти вещи не совпадают по времени.

1) Несовпадение смыслов

  • viewDidLoad:

    • вызывается, когда view создана

    • может случиться задолго до первого показа

    • обычно не повторяется

  • подписка:

    • должна быть активна, пока экран “живой” или “видимый”

    • часто должна включаться и выключаться много раз

Если подписался в viewDidLoad, а экран:

  • ушёл в background

  • перекрылся модалкой

  • был скрыт другим экраном
    то события всё равно могут продолжить приходить.

2) Типовые проблемы

  1. Дубли обработчиков

    • если подписка где-то повторяется (например, при пересоздании view), можно случайно получить несколько одинаковых подписок

    • результат: обработчик срабатывает 2-3-10 раз

  2. Утечки памяти

    • подписка удерживает объект (прямо или косвенно)

    • контроллер не деинициализируется, потому что “на него кто-то подписан”

  3. События приходят в невидимый экран

    • UI обновляется, когда пользователь экран не видит

    • возможны краши из-за обращения к состоянию, которое уже неактуально

  4. Сложные сценарии переходов

    • интерактивные dismiss/pop могут быть отменены

    • методы жизненного цикла могут вызываться не в ожидаемой паре
      В таких сценариях “подписался в didLoad, отписался в willDisappear” легко даёт расхождение.

3) Примеры, где это особенно больно

  1. NotificationCenter

NotificationCenter.default.addObserver(
    self,
    selector: #selector(handle),
    name: UIApplication.didEnterBackgroundNotification,
    object: nil
)
// если не удалить observer — проблемы (утечки, неожиданные вызовы)
  1. KVO / наблюдение

    • если не снять наблюдение, можно получить краш при деинициализации

  2. Combine / Rx

    • подписки живут дольше экрана, если их не очищать

4) Как правильнее мыслить про подписки

Чтобы не ловить баги, полезно разделять подписки на типы:

  1. Подписки, которые нужны пока экран виден

    • включать в viewWillAppear

    • выключать в viewDidDisappear

  2. Подписки, которые нужны пока существует контроллер

    • подписываться при создании (или в viewDidLoad)

    • обязательно отписываться в deinit

  3. Подписки, которые должны переживать экраны

    • выносить в сервисы / менеджеры, а не держать во вью-контроллере

5) Мини-шаблон (логика без больших блоков)

Идея: делать жизненный цикл подписки симметричным.

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    // subscribe()
}

override func viewDidDisappear(_ animated: Bool) {
    super.viewDidDisappear(animated)
    // unsubscribe()
}

deinit {
    // на всякий случай: cleanup, removeObserver, cancel tokens
}

Краткий вывод

Подписки в viewDidLoad опасны, потому что viewDidLoad почти не повторяется, а “активность экрана” повторяется постоянно. Привязывай подписки либо к появлению/исчезновению (viewWillAppear/viewDidDisappear), либо к жизни объекта (deinit) — в зависимости от смысла.

  • Аватар

    iOS Guru

    Roman Isakov

    Guru – это эксперты YeaHub, которые помогают развивать комьюнити.

Уровень

  • Рейтинг:

    5

  • Сложность:

    8

Навыки

  • IOS

    IOS

Ключевые слова

#subscription

#notificationcenter

Подпишись на iOS Developer в телеграм

  • Аватар

    iOS Guru

    Roman Isakov

    Guru – это эксперты YeaHub, которые помогают развивать комьюнити.