viewWillAppear — е метод на UIViewController, който UIKit извиква всеки път, преди екранът да стане видим за потребителя. Според Apple Developer Documentation, този метод получава булев параметър animated, който показва дали преходът се извършва с анимация. viewWillAppear — е основното място за актуализиране на данни и синхронизиране на състоянието на екрана.
Основни точки
viewWillAppear — е метод на UIViewController, който UIKit извиква непосредствено преди добавянето на View в йерархията на прозорците. В този момент View вече има окончателни размери след преминаванията на Auto Layout, но все още не е видим за потребителя — анимацията на прехода или не е започнала, или се изпълнява. Разработчикът презаписва този метод, за да извърши операции, които трябва да се случат преди всяко показване на екрана.
За разлика от viewDidLoad, който се изпълнява веднъж, viewWillAppear се извиква всеки път, когато екранът ще се появи: при първоначално отваряне, при връщане от дъщерен контролер, след затваряне на модален прозорец и при превключване на раздели на TabBar. Това го прави ключов метод за поддържане на актуално състояние на интерфейса.
Методът приема параметър animated от тип Bool, който е true, ако появяването на екрана е придружено от анимация. Този параметър е удобно да се предава на методите на NavigationBar и TabBar, които имат подобен параметър за последователно поведение.
Времето на извикване на viewWillAppear зависи от типа навигация, но общото правило е непроменливо: методът се изпълнява преди View да стане видимо. Нека разгледаме основните сценарии.
След извикване на viewDidLoad, UIKit започва подготовка за показване: View се добавя в йерархията, изпълняват се преминаванията на layout и непосредствено преди началото на анимацията на прехода се извиква viewWillAppear. В този момент екранът все още не е видим, но всички subviews имат правилни размери и тяхното съдържание може безопасно да се актуализира.
Когато потребителят натисне бутона за назад или програмно извика popViewController, UIKit се връща към предишния екран и извиква viewWillAppear на него. Това е основният сценарий, за който се използва viewWillAppear — актуализиране на списъка след добавяне на елемент или синхронизиране на настройки.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
tableView.reloadData()
updateBadgeCount()
}
След затваряне на модално представен контролер, UIKit извиква viewWillAppear на контролера, който го е представил. Този сценарий изисква специално внимание, ако използвате делегати или closure за връщане на данни — 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. Това предотвратява ненужни handler-и, когато екранът не е активен, и предпазва от изтичане на памет.
Ако екранът може да бъде скрит от приложението или минимизиран, viewWillAppear е удобно място за възстановяване на състоянието на UI: превключване на сегменти, възстановяване на позицията на scroll, нулиране на временни промени. Потребителят получава екрана в предвидима форма при всяко появяване.
На екрани, показващи броячи на непрочетени съобщения, оценки или известия, viewWillAppear е правилното място за тяхното актуализиране. Ако потребителят е могъл да промени количеството на друг екран, тук се извиква преизчисляване и актуализиране на UITabBarItem.badgeValue или персонализирани индикатори. Това гарантира, че потребителят винаги вижда актуални числа, независимо колко време е прекарал на други екрани.
Отделно трябва да се спомене работата с collectionView: ако данните на екрана са представени под формата на мрежа с клетки, съдържащи броячи или статуси, тяхното актуализиране в viewWillAppear трябва да бъде селективно. Вместо пълно reloadData, използвайте reloadItemsAtIndexPaths за видимите клетки, за да избегнете мигане и загуба на позиция на scroll.
Разбирането на разликата между 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 програмно променяте ограниченията, 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 в closure-и. Това просто действие предотвратява сривове и ненужно прерисуване на интерфейса.
Често задавани въпроси
viewWillAppear се извиква преди началото на анимацията на появяване, когато View все още не е видимо. viewDidAppear — след завършване на анимацията, когато екранът е напълно показан и достъпен за взаимодействие.
При нормални условия viewWillAppear винаги се извиква при появяване на екрана. Изключение — принудително затваряне на приложението (force quit), при което UIKit не успява да извика методите на Lifecycle.
Да, задължително. UIKit използва това извикване за вътрешна координация с UINavigationController и UITabBarController. Без super могат да се развалят жестовете и анимациите на преходите.
При всяко превключване на раздел. UIKit извиква viewWillAppear на контролера на избрания раздел веднага след като потребителят докосне съответната икона в TabBar.
Използвайте свойства на контролера или споделен data source. Преди да извикате popViewController, задайте необходимите стойности на предишния контролер и в неговия viewWillAppear те вече ще бъдат достъпни.
Резюме
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също