viewWillAppear — это метод UIViewController, который UIKit вызывает каждый раз перед тем, как экран становится видимым для пользователя. По данным Apple Developer Documentation, этот метод получает булев параметр animated, указывающий, происходит ли переход с анимацией. viewWillAppear — основное место для обновления данных и синхронизации состояния экрана.
Главное
viewWillAppear — это метод UIViewController, который UIKit вызывает непосредственно перед добавлением View в иерархию окон. В этот момент View уже имеет финальные размеры после проходов Auto Layout, но ещё не видна пользователю — анимация перехода либо не началась, либо выполняется. Разработчик переопределяет этот метод для выполнения операций, которые должны произойти перед каждым показом экрана.
В отличие от viewDidLoad, который срабатывает единожды, viewWillAppear вызывается каждый раз, когда экран собирается появиться: при стартовом открытии, при возврате с дочернего контроллера, после dismiss модального окна и при переключении вкладок TabBar. Это делает его ключевым методом для поддержания актуального состояния интерфейса.
Метод принимает параметр animated типа Bool, который равен true, если появление экрана сопровождается анимацией. Этот параметр удобно передавать в методы NavigationBar и TabBar, которые тоже имеют аналогичный параметр для согласованного поведения.
Тайминг вызова viewWillAppear зависит от типа навигации, но общее правило неизменно: метод срабатывает перед тем, как View становится видимой. Рассмотрим основные сценарии.
После вызова viewDidLoad UIKit начинает подготовку к показу: View добавляется в иерархию, запускаются проходы layout, и непосредственно перед началом анимации перехода вызывается viewWillAppear. В этот момент экран ещё не видим, но все subviews имеют корректные размеры, и можно безопасно обновлять их содержимое.
Когда пользователь нажимает back button или программно вызывает popViewController, UIKit возвращается на предыдущий экран и вызывает у него viewWillAppear. Это основной сценарий, для которого используют viewWillAppear — обновление списка после добавления элемента или синхронизация настроек.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
tableView.reloadData()
updateBadgeCount()
}
После закрытия модально представленного контроллера UIKit вызывает viewWillAppear у контроллера, который его представил. Этот сценарий требует особого внимания, если вы используете делегаты или замыкания для передачи данных назад, — viewWillAppear гарантирует, что экран обновится после получения результата.
TabBarController вызывает viewWillAppear у контроллера выбранной вкладки каждый раз при переключении. Если на вкладке отображаются динамические данные — курс валют, уведомления, статус пользователя — viewWillAppear идеальное место для их обновления.
viewWillAppear решает несколько конкретных задач, которые невозможно или неоптимально выполнять в других методах. Рассмотрим основные из них.
Самое частое применение viewWillAppear — перезагрузка UITableView или UICollectionView при каждом появлении экрана. Если данные могли измениться на предыдущем экране (добавление элемента, изменение статуса), вызов reloadData в viewWillAppear гарантирует, что пользователь видит актуальную информацию.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
viewModel.synchronize()
tableView.reloadData()
}
В viewWillAppear удобно настраивать внешний вид NavigationBar: скрывать или показывать его, менять цвет, устанавливать large title. Если на разных экранах NavigationBar выглядит по-разному, viewWillAppear — правильное место для этих изменений, так как viewDidLoad вызывается только один раз.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.setNavigationBarHidden(
false, animated: animated
)
navigationController?.navigationBar.prefersLargeTitles = true
tabBarController?.tabBar.isHidden = false
}
Уведомления, которые имеют смысл только когда экран видим — клавиатурные, уведомления об изменении контента — подписывают в viewWillAppear и отписывают в viewDidDisappear. Это предотвращает лишние обработчики, когда экран не активен, и защищает от утечек памяти.
Если экран может быть скрыт приложением или свёрнут, viewWillAppear — удобное место для восстановления состояния UI: переключения сегментов, восстановления позиции скролла, сброса временных изменений. Пользователь получает экран в предсказуемом виде при каждом появлении.
На экранах, отображающих счётчики непрочитанных сообщений, оценок или уведомлений, viewWillAppear — правильное место для их обновления. Если пользователь мог изменить количество на другом экране, здесь вызывают пересчёт и обновление UITabBarItem.badgeValue или кастомных индикаторов. Это гарантирует, что пользователь всегда видит актуальные числа независимо от того, как долго он находился на других экранах.
Отдельно стоит отметить работу с collectionView: если данные на экране представлены в виде сетки с ячейками, содержащими счётчики или статусы, их обновление в viewWillAppear должно быть выборочным. Вместо полного reloadData используйте reloadItemsAtIndexPaths для видимых ячеек, чтобы избежать мерцания и потери позиции скролла.
Понимание разницы между viewWillAppear и viewDidLoad — основа правильной архитектуры UIViewController. Эти методы имеют разную частоту вызова, разный контекст и разное назначение.
viewDidLoad вызывается один раз и подходит для настройки, которая не меняется со временем: регистрация ячеек, установка делегатов, инициализация констант. viewWillAppear вызывается при каждом появлении и подходит для операций, которые должны повторяться: обновление данных, настройка видимых элементов, синхронизация состояния.
| Характеристика | viewDidLoad | viewWillAppear |
|---|---|---|
| Частота | Один раз | Каждый раз при появлении |
| View видима | Нет | Нет (скоро станет видимой) |
| Размеры View | Не финальные | Финальные |
| Подходит для | Одноразовой настройки | Обновления и синхронизации |
| Анимация | Неприменимо | Параметр animated |
Золотое правило: если операция должна выполниться только один раз — кладите в viewDidLoad. Если каждый раз при возврате на экран — кладите в viewWillAppear.
Неправильное использование viewWillAppear может привести к проблемам с производительностью, избыточным обновлениям и неконсистентному состоянию интерфейса. Рассмотрим наиболее частые ошибки.
Первая ошибка — дублирование логики из viewDidLoad. Если вы регистрируете ячейки таблицы и в viewDidLoad, и в viewWillAppear — регистрация будет выполняться многократно, хотя достаточно однократной настройки. Переместите все одноразовые конфигурации в viewDidLoad.
Вторая ошибка — безусловный reloadData при каждом появлении. Если данные не менялись, перезагрузка таблицы вызывает лишние запросы к data source и перерисовку ячеек, снижая производительность. Проверяйте, действительно ли состояние изменилось, перед вызовом reloadData.
Третья ошибка — работа с сетевыми запросами без учёта, что экран может быть снова скрыт до завершения запроса. Если в viewWillAppear вы запускаете URLSession-запрос, а пользователь сразу уходит на другой экран, результат может быть применён к уже скрытому View. Используйте отменяемые задачи или проверяйте isViewLoaded и window перед обновлением.
Четвёртая ошибка — забыли вызвать super. Невызов super.viewWillAppear может нарушить работу родительских контроллеров (UINavigationController, UITabBarController) и привести к некорректной обработке жестов и переходов. super должен быть вызван всегда.
Пятая ошибка — изменение констрейнтов без вызова layoutIfNeeded. Если в viewWillAppear вы программно меняете constraints, UIKit не применяет их мгновенно — изменения накапливаются до следующего прохода layout. Для немедленного применения изменений после модификации констрейнтов вызывайте view.layoutIfNeeded(). Это особенно важно при настройке высоты элементов, зависящих от содержимого.
Шестая ошибка — попытка выполнить анимацию в viewWillAppear. Как упоминалось выше, UIKit ещё обрабатывает переходную анимацию, и ваша анимация может конкурировать с системной. Если вам нужно, чтобы элемент появился с эффектом, используйте входящую анимацию в viewDidAppear, а в viewWillAppear только настройте начальное состояние: прозрачность 0, transform в масштабе 0.8 и так далее.
Седьмая ошибка — игнорирование параметра animated. Некоторые разработчики не проверяют значение animated в viewWillAppear и выполняют операции, которые должны зависеть от наличия анимации. Например, скрытие NavigationBar при animated = false можно сделать без анимации, а при animated = true — с анимацией, чтобы переход выглядел плавно. Всегда передавайте параметр animated в соответствующие методы UIKit.
Восьмая ошибка — модификация UI при невидимом экране. Если в viewWillAppear вы запускаете сетевой запрос, а его completion block обновляет UI, когда экран мог уже исчезнуть, пользователь увидит мерцание или неконсистентное состояние. Всегда проверяйте isViewLoaded и window перед обновлением UI в замыканиях. Это простое действие предотвращает краши и лишние перерисовки интерфейса.
Часто задаваемые вопросы
viewWillAppear вызывается до начала анимации появления, когда View ещё не видна. viewDidAppear — после завершения анимации, когда экран полностью отобразился и доступен для взаимодействия.
В нормальных условиях viewWillAppear вызывается всегда при появлении экрана. Исключение — force quit приложения, при котором UIKit не успевает вызвать методы Lifecycle.
Да, обязательно. UIKit использует этот вызов для внутренней координации с UINavigationController и UITabBarController. Без super могут сломаться жесты и анимации переходов.
При каждом переключении на вкладку. UIKit вызывает viewWillAppear у контроллера выбранной вкладки сразу после того, как пользователь касается соответствующей иконки в TabBar.
Используйте свойства контроллера или общий data source. Перед вызовом popViewController установите нужные значения на предыдущем контроллере, и в его viewWillAppear они уже будут доступны.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также