Яка різниця між -viewWillAppear: та -viewDidAppear:?


131

У чому різниця між -[UIViewController viewWillAppear:]і -[UIViewController viewDidAppear:]?


1
дякую BoltClock, але будь ласка, наведіть мені приклад обох, якщо це можливо ..
PJR

3
@BoltClock було б добре, якби це було правдою. Я здогадуюсь, що 15 людей, які підтримали голос, прочитали ім'я методу, але насправді ніколи його не вимірювали ... Приїхали сюди з Google, оскільки це НЕ різниця між ними
Адам

1
Конкретніше: parentView.viewDidAppear називається ДОЛГО ЧАС до того, як Apple фактично відобразить parentView ... Apple спочатку (атомно) фарбує всі підпогляди ... і якщо у вас багато підпогляду або складних, то "viewDidAppear" можна назвати десятками або сотні мілісекунд занадто рано :(.
Адам

Відповіді:


292

Загалом, це те, що я роблю:

1) ViewDidLoad - Кожного разу, коли я додаю елементи контролю до представлення, яке повинно з’являтися разом із представленням даних, я одразу ставлю його у метод ViewDidLoad. В основному цей метод називається всякий раз, коли подання завантажується в пам'ять. Так, наприклад, якщо мій погляд є формою з 3 мітками, я б додав сюди мітки; погляд ніколи не буде без цих форм.

2) ViewWillAppear : я зазвичай використовую ViewWillAppear просто для оновлення даних у формі. Отже, у прикладі вище, я б використав це, щоб фактично завантажити дані з мого домену у форму. Створення UIViews є досить дорогим, і вам слід максимально уникати цього робити методом ViewWillAppear, тому що, коли це викликається, це означає, що iPhone вже готовий показати UIView користувачеві, і все те, що ви робите тут, впливатиме на продуктивність дуже помітно (наприклад, анімація затримується тощо).

3) ViewDidAppear : Нарешті, я використовую ViewDidAppear для запуску нових потоків до речей, які потребуватимуть тривалого часу, як, наприклад, для виклику веб-сервісу, щоб отримати додаткові дані для форми вище. Добре, що тому, що перегляд вже існує і відображається користувачеві, ви можете показати приємне повідомлення "Очікування" користувачеві під час отримання даних.


4
Вибачте, але що ви маєте на увазі під "завантаженням даних з мого домену у форму" viewWillAppear? Ви маєте на увазі завантаження через мережу? Але ви також пропонуєте завантажити речі в viewDidAppear?
Philip007

1
@ Philip007 Я думаю, що Stack посилається на такий тип домену: en.wikipedia.org/wiki/Domain-specific_modeling . Дані завантажуються з ваших моделей або подібних.
dentarg

2
Ця відповідь повинна бути в документах. Це було дуже корисно для з'ясування різниці між трьома методами. Дякую!
GangstaGraham

1
+1 У мене було трохи плутанини, розуміючи різницю між цими трьома, але ви просто очистили це більш ніж ідеально @ChetanBhalara
Chisx

@ChetanBhalara, але якщо ти покладеш довгу роботу, ViewDidAppearти легко
змусиш

46

viewDidLoad === >>> Помістіть тут свій ініціалізаційний код. Не вводьте динамічні дані, які можуть змінюватися протягом життєвого циклу перегляду. Отже, якщо ви витягуєте дані з основних даних, ви не хочете робити це тут, якщо це може змінитися протягом життя представлення даних. Наприклад: скажіть, у вас є контролер вкладок. Ви переходите з tab1 на tab2 і щось змінюєте на моделі в tab2. Якщо ви повернетесь до tab1 і ваш код моделі було зроблено у viewDidLoad, це не буде оновлено (якщо ви не використовуєте KVO або NSFetchedResultsController тощо).

viewWillAppear === >>> Це викликається кожного разу, коли огляд буде відображатися, незалежно від того, перегляд вже є в пам'яті. Покладіть сюди свій динамічний код, наприклад логіку моделі.

viewDidAppear === >>> Помістіть сюди дорогі операції, які ви хочете виконати, лише якщо ви впевнені, що перегляд є на екрані, наприклад, мережеві дзвінки.

Зверніть увагу: якщо ваш додаток фоновим і повертається на передній план, вам потрібно обробити це за допомогою NSNotificationCenter. Я написав код для цього в коментарях нижче. Ви можете подумати, що viewWillAppear / viewDidAppear запустить. Поставте туди перерву і протестуйте її. Це не вогонь. Отже, якщо щось змінилося для вашої програми, поки воно було у фоновому режимі, вам потрібно буде оновити це за допомогою сповіщень.


1
Чи запускаються ViewWill або ViewDid щоразу, коли ви скасовуєте мінімізацію програми?
Jeef

2
@Jeef Це відмінне запитання. Не запускається, якщо додаток не вбито системою або користувачем, перебуваючи у фоновому режимі. Що вам потрібно зробити, щоб отримувати сповіщення, коли додаток не зводиться до мінімуму, ви повинні використовувати NSNotificationCenter та addObserver для імені UIApplicationWillEnterForegroundNotification. Селектор повинен бути applicationWillEnterForeground: він має параметр «Параметр NSNotification». Введіть свій код у цей метод для перезавантаження даних тощо. Що ви можете зробити, це створити метод перезавантаження, який ви викликаєте з цього методу, а також viewDidAppear, якщо вони повинні бути однаковими.
smileBot

2
@Jeef щось подібне: - (void) viewDidLoad {[[[NSNotificationCenter defaultCenter] addObserver: самовідбір: @selector (applicationWillEnterForeground :) ім'я: UIApplicationWillEnterForegroundNotification object: nil]; } - (недійсна) програмаWillEnterForeground: (NSNotification *) notif {// відповісти тут будь-чим}
smileBot

12

viewWillAppearМетод викликається перед завантаженням фактичного подання.

viewDidAppearМетод викликається , коли уявлення вже завантажений, і ви хочете , щоб показати що - то.


9

viewWillAppear:
■ Викликається до того, як подання буде додано до ієрархії перегляду вікон
■ Зателефоновано до [vc.view layoutSubviews] (за необхідності)
viewDidAppear :
■ Викликається після того, як подання буде додано до ієрархії перегляду
■ Викликається після [vc.view layoutSubviews] (якщо необхідно)


7

Кілька спостережень:

  • viewDidLoadМетод викликається , коли представлення першого примірника. IBOutletпосилання підключені до моменту, коли це було викликано, але не раніше. Однак, frameпогляд може не встановитись до моменту, коли це було викликано. Це чудове місце для додавання / налаштування підпрезентацій та пов'язаних з ними обмежень. Але якщо ви робите будь-яку ручну конфігурацію frameзначень на основі розмірів основного виду, конфігурацію цих кадрів слід відкладати до viewWillAppearабо viewDidLayoutSubviews.

  • viewWillAppearМетод викликається , коли уявлення виду в ієрархії уявлень збирається почати. Зокрема, це називається на початку анімації (якщо вона є) подання виду. Його супутником, viewWillDisappearочевидно, називають, коли починається перехід від цього погляду.

  • viewDidAppearМетод викликається , коли робиться презентація зору, в зокрема , коли - небудь , і все пов'язані з ним анімація завершена. Його супутниця, viewDidDisappearочевидно, називається, коли здійснюється перехід від цього погляду.

Два важливих застереження:

  • viewDidLoadназивається один раз і лише один раз, коли погляд вперше інстанціюється. З іншого боку, viewWillAppearі viewDidAppearбуде називатися не тільки при вперше представленому погляді, але кожного наступного разу той самий погляд, про який йде мова, повторно подається. Наприклад, коли ви вперше представите подання, всі три ці методи будуть викликані. Якщо згодом поданий перегляд представляє інший вигляд, який згодом буде відхилено, то, viewWillAppearі viewDidAppear, як правило, буде викликано знову, коли відповідний вид буде доданий і анімований назад в ієрархію перегляду, але viewDidLoadне буде. viewDidLoadвикликається лише тоді, коли цей конкретний екземпляр вперше створений.

    Отже, якщо ви хочете щось робити щоразу, коли вигляд знову з’являється (наприклад, ви відхиляєте його чи повертаєтесь до нього), робіть це в viewWillAppearабо viewDidAppear. Якщо ви хочете, щоб це сталося лише тоді, коли подання представлено вперше, зробіть це в viewDidLoad.

  • Заклик viewWillAppearне гарантує, що перехід до цього погляду коли-небудь буде завершений. Зокрема, якщо ви використовуєте інтерактивний перехід, який керується вводом користувача в режимі реального часу, але цей інтерактивний перехід можна скасувати. Тобто, тільки тому viewWillAppear, що називається, це не означає, що viewDidAppearбуде покликано. Як правило, так є, але якщо інтерактивний жест скасовано, він не стане (тому що перехід ніколи не завершився).

    На WWDC 2013, в контексті інтерактивних переходів, ведучий пожартував, що їх слід перейменувати viewWillAppearна " viewMightAppear, або viewWillProbablyAppearабо iReallyWishThisViewWouldAppear".

    Приклад вбудованого інтерактивного жесту - це коли ви користуєтесь a UINavigationControllerі "проведіть пальцем з лівого краю", щоб ініціювати спливаюче вікно перегляду. Заклик viewWillAppearбуде викликано для подання, на яке ви вискакуєте, але якщо ви скасуєте цей "пальцем з лівого краю", щоб повернутися до того виду, з якого ви розпочали цей поп-жест, спливаюче вікно скасовується, і viewDidAppearдля перегляду, який ви почали поп назад до ніколи не буде викликаний.

    Чистий ефект цього полягає в тому, що ви повинні бути обережними, щоб ви не писали код, який передбачає, що після кожного дзвінка в viewWillAppearкінцевому підсумку буде здійснено дзвінок на viewDidAppear. Якщо перехід скасується, це не буде.


5

viewwillappear зателефонує перед завантаженням представлення, щоб ви могли виконати певну задачу перед завантаженням цього виду, а viewdidappear зателефонує після завантаження перегляду, тому завдання публікації буде виконано в цьому методі


4

Різниця між "волею" і "зробив" ... Як випливає з назви, вигляд viewWillAppear буде викликаний до того, як перегляд збирається з'явитися, а viewDidAppear викликається, коли перегляд з'явився.


подивіться на прийнятий відповідь, який містить 70+ оновлень. :)
PJR

4

1) ViewWillAppear : Перегляд фактично завантажується в пам'ять, викликається один раз у контролері перегляду та має його кадр, але все ще не з’являється користувачеві

2) ViewDidAppear : Контролер додано до ієрархії подання, щоб ви могли представити наступний контролер, а також перегляд макетував підпогляди



3

Підсумовуючи:

-viewWillAppear -> оновити дані (перезавантажити дані з подання таблиці)

-viewDidAppear -> дорогі операції (API-дзвінок із приємною швидкістю прогресу!)


1

Як випливає з назви viewWillAppear, виклик викликається до того, як перегляд збирається з'явитися, і viewDidAppearвикликається, коли перегляд з'явився.


0

Usecase , тобто коли я повинен використовувати який?

viewDidLoad - коли мітки, кнопки (i, e будь-які елементи управління / підпогляди) підключені до файлу інтерфейсу View, і якщо ви хочете завантажити все це одночасно з представленням ViewController, і якщо ви хочете один раз завантажити це в пам'ять і бути зроблено з ним

viewWillAppear- скажімо, ви хочете змінити колір тла перегляду щоразу, коли на екрані з'явиться viewController. Або більш реалістично, якщо ви хочете, щоб колір фону DarkMode був у нічний час доби та світлий колір перегляду фону в денний час, перейдіть за цим кодом уviewWillAppear

Ще один добрий футляр тут https://stackoverflow.com/a/39395865/5438240

Також зауважте, що якщо ви використовуєте стек навігації ( UINavigationController), viewController, який збирається спливати, має viewWillDisappear()виклик, а ViewController, який буде розташований у верхній частині стека, буде viewWillAppear()викликати

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.