viewDidAppear — це метод UIViewController, який UIKit викликає після того, як екран повністю з'явився на дисплеї та всі анімації переходу завершені. За даними Apple Developer Documentation, цей метод гарантує, що View видима користувачу та готова до взаємодії. viewDidAppear — оптимальне місце для запуску анімацій, трекінгу та асинхронних операцій.
Головне
viewDidAppear — це метод UIViewController, який UIKit викликає після того, як View була додана в ієрархію вікон та анімація переходу повністю завершена. У цей момент екран перебуває у фінальному стані: він видимий, з ним можна взаємодіяти, усі анімації UIKit зупинені. Розробник перевизначає цей метод для виконання дій, які вимагають, щоб екран гарантовано був перед очима користувача.
На відміну від viewWillAppear, де екран лише готується до показу, viewDidAppear сигналізує, що користувач уже бачить інтерфейс. Це критична відмінність: старт анімації у viewWillAppear може призвести до пропущених кадрів, оскільки UIKit ще обробляє перехід. У viewDidAppear перехід завершений, і ресурси контролера можуть бути використані для відмальовування нового контенту.
Метод приймає параметр animated типу Bool, аналогічний viewWillAppear. Якщо true — поява екрана супроводжувалася анімацією. Цей параметр можна використовувати для адаптації поведінки UI: наприклад, для пропуску вхідної анімації при неанімованому поверненні.
viewDidAppear викликається у всіх сценаріях, коли екран завершив процес появи. Розглянемо основні випадки з точки зору iOS-розробника.
Після того як UINavigationController завершив анімацію push або pop, на цільовому контролері викликається viewDidAppear. Для першого екрана в стеку він спрацьовує після початкової анімації відкриття. Це основний сценарій, і саме на нього орієнтуються при розміщенні логіки у viewDidAppear.
Коли користувач закриває модально представлений контролер і повертається на попередній, UIKit викликає viewDidAppear у повернутого контролера. При цьому параметр animated відповідатиме тому, чи був виконаний dismiss з анімацією. Цей момент важливий для оновлення UI після отримання даних із дочірнього екрана.
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
logScreenView()
startOnboardingAnimation()
}
UITabBarController викликає viewDidAppear на контролері вибраної вкладки після завершення перемикання. Це відмінність від viewWillAppear, який спрацьовує на початку перемикання. Якщо на вкладці є анімація привітання або необхідно відстежувати активний час, viewDidAppear — правильне місце.
Коли застосунок повертається з background у foreground, у видимого контролера можуть бути викликані viewWillAppear і viewDidAppear, якщо життєвий цикл View був тимчасово призупинений. Однак для надійного відстеження повернення з фону використовуйте UIApplication.willEnterForegroundNotification окремо.
viewDidAppear вирішує завдання, які вимагають видимого екрана для коректного виконання. Розглянемо ключові сценарії використання в реальних проєктах.
Найпоширеніше завдання viewDidAppear — трекінг перегляду екрана. Аналітичні системи, такі як Firebase Analytics, Amplitude або Mixpanel, повинні отримувати події лише після того, як екран дійсно показаний користувачу. Відправлення події у viewWillAppear може занижувати час перегляду та створювати хибні спрацьовування.
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
Analytics.logEvent(
name: "screen_view",
parameters: [
"screen_name": "ProfileScreen",
"screen_class": String(describing: self)
]
)
}
Анімації, які мають початися після появи екрана — поява елементів із затримкою, паралакс, туторіал — запускають у viewDidAppear. У цей момент графічний контекст повністю готовий, і анімація буде плавною, без випадання кадрів на старті. Це особливо важливо для анімацій із використанням UIViewPropertyAnimator.
Важкі асинхронні операції — завантаження зображень високої роздільної здатності, парсинг великих JSON, ініціалізація відео — краще запускати у viewDidAppear, а не у viewDidLoad або viewWillAppear. На момент виклику методу користувач уже бачить інтерфейс, а отже, можна показати скелетон або лоадер, не затримуючи появу екрана.
Якщо на екрані є елементи, які потребують періодичного оновлення — таймер зворотного відліку, індикатор завантаження, анімація прогресу — їх запускають у viewDidAppear та зупиняють у viewDidDisappear. Це запобігає роботі таймерів, коли екран не видимий, економлячи заряд батареї та ресурси CPU.
Медіаконтент — відео, аудіо, анімації Lottie — запускають саме у viewDidAppear, а не раніше. Якщо почати відтворення у viewWillAppear, користувач пропустить перші секунди, поки екран ще з'являється. У viewDidAppear ви можете запустити AVPlayer або анімацію Lottie з упевненістю, що користувач бачить контент із першого кадра. Це особливо важливо для onboarding-екранів та заставок, де важливий точний таймінг.
Правильний момент запуску анімації безпосередньо впливає на сприйняття плавності інтерфейсу. Різниця між запуском у viewWillAppear і viewDidAppear може бути непомітною на простих анімаціях, але критичною для складних сцен.
Коли UIKit виконує push-перехід між екранами, він створює скриншоти, анімує їх та одночасно викликає viewWillAppear на новому контролері. Якщо в цей момент запустити важку анімацію — паралакс, blur, трансформацію — UIKit може пропустити кадри перехідної анімації, створюючи ефект смикання. viewDidAppear гарантує, що перехідна анімація завершена, і ви отримуєте повний контроль над рендерингом.
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
UIView.animate(
withDuration: 0.6,
delay: 0.3,
usingSpringWithDamping: 0.8,
initialSpringVelocity: 0.5
) {
self.cardView.alpha = 1.0
self.cardView.transform = .identity
}
}
Використовуйте затримки та демпфування для створення природної каскадної появи елементів. Такий підхід покращує сприйняття інтерфейсу та збільшує dwell time — користувач довше вивчає контент, що позитивно впливає на поведінкові метрики.
Неправильне використання viewDidAppear може призвести до проблем із продуктивністю, неочікуваної поведінки анімацій та надмірного трекінгу. Розглянемо часті помилки.
Перша помилка — множинні виклики. viewDidAppear може викликатися кілька разів за певних сценаріїв: перемикання вкладок, повернення з фону, модальні переходи. Якщо в методі виконується важка операція без перевірки флага, вона дублюватиметься. Використовуйте флаг hasAppeared або dispatchOnce для одноразових дій.
Друга помилка — запуск мережевих запитів без скасування при приховуванні. Якщо користувач залишає екран до завершення запиту, результат може бути застосований до вже прихованої View. Використовуйте скасовувані URLSessionTask та завершуйте їх у viewDidDisappear.
Третя помилка — трекінг у viewWillAppear замість viewDidAppear. Деякі розробники відправляють події analytics у viewWillAppear, але це дає хибні спрацьовування, якщо екран не з'явився (наприклад, при скасованому жесті pop). viewDidAppear — єдиний надійний індикатор того, що користувач дійсно побачив екран.
Четверта помилка — забули super. Виклик super.viewDidAppear необхідний для коректної роботи UINavigationController, UITabBarController та UISplitViewController. Без нього можуть зламатися стандартні механізми навігації та оновлення інтерфейсу.
П'ята помилка — зміна орієнтації або розміру екрана без урахування viewDidLayoutSubviews. Якщо ваша анімація у viewDidAppear залежить від фінальних розмірів View, пам'ятайте, що viewDidLayoutSubviews міг викликатися кілька разів до viewDidAppear. При першій появі екрана layout завершується до виклику viewDidAppear, але при подальших змінах розміру — наприклад, при повороті пристрою — viewDidAppear може не викликатися, і ваша анімація не запуститься. У таких випадках використовуйте viewDidLayoutSubviews із перевіркою флага firstLayout.
Правильна реалізація передбачає збереження посилання на об'єкт анімації та її явне скасування при залишенні екрана. Шоста помилка — запуск нескінченних анімацій без флага зупинки. Якщо у viewDidAppear ви запускаєте повторювану анімацію (наприклад, пульсуючий індикатор або обертовий лоадер завантаження), але не зупиняєте її у viewDidDisappear, анімація витрачатиме ресурси GPU, навіть коли екран прихований. Завжди зберігайте посилання на активну анімацію та викликайте removeAllAnimations або setCompletion у відповідному методі завершення життєвого циклу.
Сьома помилка — ігнорування viewDidDisappear для зупинки активностей. Якщо ви почали прослуховування GPS, акселерометра або гіроскопа у viewDidAppear, обов'язково зупиніть його у viewDidDisappear. Інакше датчики продовжать роботу у фоні, витрачаючи батарею, навіть якщо користувач давно перейшов на інший екран. Використовуйте парні виклики start і stop у відповідних методах життєвого циклу — це гарантує коректне управління ресурсами пристрою.
Часті запитання
viewWillAppear викликається до анімації появи, коли екран ще не видимий. viewDidAppear — після повного завершення анімації, коли екран видимий і доступний для взаємодії.
У viewDidAppear перехідна анімація UIKit уже завершена, і всі ресурси рендерингу доступні вашому контролеру. Запуск анімації раніше може призвести до пропущених кадрів і смиканого інтерфейсу.
У нормальному життєвому циклі ні — viewDidAppear завжди слідує за viewWillAppear. Однак за деяких сценаріїв відновлення стану система може викликати лише viewDidAppear.
Додайте перевірку флага firstAppearance або використовуйте комбінацію лічильника та назви екрана. Наприклад, відправляйте подію screen_view лише при firstAppearance = true, потім скидайте флаг.
При поверненні з background UIKit може викликати viewDidAppear на видимому контролері, якщо View була вивантажена з пам'яті. Для надійного відстеження використовуйте повідомлення AppDelegate.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також