Jaka jest różnica między -viewWillAppear: i -viewDidAppear :?

132

Jaka jest różnica między -[UIViewController viewWillAppear:]i -[UIViewController viewDidAppear:]?

PJR
źródło
1
dzięki BoltClock, ale proszę o przykład obu, jeśli to możliwe ..
PJR
3
@BoltClock byłoby miło, gdyby to była prawda. Zgaduję, że 15 osób, które głosowały za, przeczytało nazwę metody, ale nigdy jej nie zmierzyło ... Przyszło tutaj z Google, ponieważ to NIE jest różnica między nimi
Adam
1
W szczególności: parentView.viewDidAppear jest nazywany DŁUGIM CZASEM, zanim Apple faktycznie wyświetli parentView ... Apple najpierw (niepodzielnie) maluje wszystkie widoki podrzędne ... a jeśli masz wiele widoków podrzędnych lub złożonych, to „viewDidAppear” można nazwać dziesiątkami lub o setki milisekund za wcześnie :(.
Adam

Odpowiedzi:

293

Generalnie robię to:

1) ViewDidLoad - za każdym razem, gdy dodaję kontrolki do widoku, który powinien pojawić się razem z widokiem, od razu umieszczam go w metodzie ViewDidLoad. Zasadniczo ta metoda jest wywoływana za każdym razem, gdy widok został załadowany do pamięci. Na przykład, jeśli mój widok jest formularzem z 3 etykietami, dodałbym tutaj etykiety; widok nigdy nie będzie istniał bez tych form.

2) ViewWillAppear : Zwykle używam ViewWillAppear do aktualizacji danych w formularzu. W powyższym przykładzie użyłbym tego do załadowania danych z mojej domeny do formularza. Tworzenie UIViews jest dość drogie i powinieneś unikać robienia tego w jak największym stopniu w metodzie ViewWillAppear, ponieważ kiedy to zostanie wywołane, oznacza to, że iPhone jest już gotowy do pokazania użytkownikowi UIView i wszystkiego, co tutaj robisz wpłynie na wydajność w bardzo widoczny sposób (np. opóźnienie animacji itp.).

3) ViewDidAppear : Wreszcie używam ViewDidAppear, aby rozpocząć nowe wątki do rzeczy, których wykonanie zajęłoby dużo czasu, na przykład wywołanie usługi sieciowej w celu uzyskania dodatkowych danych dla powyższego formularza. już istnieje i jest wyświetlany użytkownikowi, możesz wyświetlić użytkownikowi przyjemną wiadomość „Oczekiwanie” podczas pobierania danych.

Chetan Bhalara
źródło
4
Przepraszam, ale co masz na myśli, mówiąc „załaduj dane z mojej domeny do formularza” w viewWillAppear? Masz na myśli pobieranie przez sieć? Ale sugerujesz również pobieranie rzeczy w viewDidAppear?
Philip007
1
@ Philip007 Myślę, że Stack odnosi się do tego typu domeny: en.wikipedia.org/wiki/Domain-specific_modeling . Dane są ładowane z modeli lub podobnych.
dentarg,
2
Ta odpowiedź powinna znajdować się w docs. To było naprawdę pomocne w wyjaśnieniu różnicy między tymi trzema metodami. Dziękuję Ci!
GangstaGraham
1
+1 Miałem trochę zamieszania, rozumiejąc różnicę między tymi trzema, ale właśnie wyjaśniłeś to bardziej niż perfekcyjnie @ChetanBhalara
Chisx
@ChetanBhalara, ale jeśli włożysz dużo pracy ViewDidAppear, łatwo wprowadzisz użytkowników w błąd co do interfejsu użytkownika :)
hqt
46

viewDidLoad === >>> Umieść tutaj swój kod inicjalizacyjny. Nie umieszczaj danych dynamicznych, które mogą ulec zmianie w trakcie cyklu życia widoku. Jeśli więc pobierasz dane z podstawowych danych, nie chcesz tego robić tutaj, jeśli może się to zmienić w trakcie życia widoku. Na przykład: powiedz, że masz kontroler kart. Przełączasz się z tab1 na tab2 i zmieniasz coś w modelu w tab2. Jeśli wrócisz do tab1, a kod modelu został utworzony w viewDidLoad, nie zostanie to zaktualizowane (zakładając, że nie używasz KVO ani NSFetchedResultsController itp.).

viewWillAppear === >>> Jest to wywoływane za każdym razem, gdy widok ma się pojawić, niezależnie od tego, czy jest już w pamięci. Umieść tutaj swój kod dynamiczny, taki jak logika modelu.

viewDidAppear === >>> Umieść tutaj kosztowne operacje, które chcesz wykonać tylko wtedy, gdy masz pewność, że widok jest wyświetlany na ekranie, na przykład połączenia sieciowe.

Uwaga: jeśli Twoja aplikacja działa w tle i powraca do pierwszego planu, musisz to zrobić za pomocą NSNotificationCenter. Napisałem kod w komentarzach poniżej. Możesz pomyśleć, że viewWillAppear / viewDidAppear zadziała. Umieść tam punkt przerwania i przetestuj go. Nie strzela. Jeśli więc coś się zmieniło w Twojej aplikacji, gdy działała w tle, musisz to zaktualizować za pomocą powiadomień.

smileBot
źródło
1
Czy ViewWill lub ViewDid są uruchamiane za każdym razem, gdy usuwasz minimalizację aplikacji?
Jeef
2
@Jeef To jest doskonałe pytanie. Żadne z nich nie jest uruchamiane, chyba że aplikacja zostanie zabita przez system lub użytkownika w tle. Aby otrzymać powiadomienie, gdy aplikacja jest niezminimalizowana, musisz użyć NSNotificationCenter i addObserver dla nazwy UIApplicationWillEnterForegroundNotification. Selektorem powinien być applicationWillEnterForeground: ma parametr NSNotification. Umieść swój kod w tej metodzie, aby przeładować dane, itp. Co możesz zrobić, to utworzyć metodę reload, którą wywołujesz z tej metody, a także viewDidAppear, jeśli muszą być takie same.
smileBot
2
@Jeef coś takiego: - (void) viewDidLoad {[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector (applicationWillEnterForeground :) name: UIApplicationWillEnterForegroundNotification object: nil]; } - (void) applicationWillEnterForeground: (NSNotification *) notif {// odpowiedz tutaj cokolwiek}
smileBot
12

viewWillAppearMetoda jest wywoływana przed załadowaniem rzeczywisty widok.

viewDidAppearMetoda jest wywoływana, gdy widok jest już załadowany, i chcesz pokazać coś.

puneet kathuria
źródło
9

viewWillAppear:
■ Wywoływane przed dodaniem widoku do hierarchii widoków okien
■ Wywoływane przed [vc.view layoutSubviews] (jeśli to konieczne)
viewDidAppear :
■ Wywoływane po dodaniu widoku do hierarchii widoków
■ Wywoływane po [vc.view layoutSubviews] (Jeśli to konieczne)

andyqee
źródło
7

Kilka uwag:

  • viewDidLoadMetoda jest wywoływana, gdy widok jest pierwsza instancja. IBOutletodniesienia są podłączane do czasu wywołania tego, ale nie wcześniej. Jednak framewidok może nie zostać ustalony przed wywołaniem tego. To świetne miejsce do dodawania / konfigurowania podglądów podrzędnych i powiązanych z nimi ograniczeń. Ale jeśli wykonujesz jakąkolwiek ręczną konfigurację framewartości na podstawie wymiarów widoku głównego, konfigurację tych ramek należy odłożyć do viewWillAppearlub viewDidLayoutSubviews.

  • viewWillAppearMetoda jest wywoływana, gdy przedstawienie widoku w hierarchii widoku ma się rozpocząć. Warto zauważyć, że jest to wywoływane na początku animacji (jeśli występuje) prezentacji widoku. Jego towarzysz, viewWillDisappearjest oczywiście nazywany, gdy zaczyna się przejście od tego widoku.

  • viewDidAppearMetoda jest wywoływana, gdy przedstawienie widoku odbywa się, w szczególności, gdy wszelkie związane animacja została zakończona. Jego towarzysz, viewDidDisappearjest oczywiście nazywany, gdy następuje przejście od tego widoku.

Dwa ważne zastrzeżenia:

  • viewDidLoadjest wywoływana raz i tylko raz, podczas pierwszego tworzenia wystąpienia widoku. Z drugiej strony, viewWillAppeari viewDidAppearbędzie wywoływana nie tylko przy pierwszym przedstawieniu widoku, ale za każdym razem ponownie ten sam widok, o którym mowa. Na przykład, gdy po raz pierwszy przedstawiasz widok, zostaną wywołane wszystkie trzy metody. Jeśli dany widok przedstawia następnie inny widok, który jest następnie odrzucany, viewWillAppeari viewDidAppearbędzie generalnie wywoływany ponownie, gdy dany widok zostanie dodany i animowany z powrotem do hierarchii widoków, ale viewDidLoadtak się nie stanie. viewDidLoadjest wywoływana tylko wtedy, gdy ta konkretna instancja jest tworzona po raz pierwszy.

    Tak więc, jeśli chcesz coś zrobić za każdym razem, gdy pojawia się ponownie widok (np. Zamykasz go lub wracasz do niego), zrób to w viewWillAppearlub viewDidAppear. Jeśli chcesz, aby działo się to tylko wtedy, gdy widok jest tworzony po raz pierwszy, zrób to w viewDidLoad.

  • Wywołanie viewWillAppearnie gwarantuje, że przejście do tego widoku kiedykolwiek zostanie zakończone. W szczególności, jeśli używasz przejścia interaktywnego, które jest sterowane danymi wejściowymi użytkownika w czasie rzeczywistym, ale to przejście interaktywne można anulować. viewWillAppearTo znaczy , tylko dlatego, że jest wezwany, nie oznacza, że viewDidAppearzostanie wezwany. Ogólnie tak jest, ale jeśli gest interaktywny zostanie anulowany, nie będzie (ponieważ przejście nigdy się nie zakończyło).

    Na WWDC 2013, w ramach interaktywnych przejściami, prezenter żartował, że powinni zmienić nazwę viewWillAppearna „ viewMightAppearalbo viewWillProbablyAppear, albo iReallyWishThisViewWouldAppear”.

    Przykładem wbudowanego gestu interaktywnego jest użycie a UINavigationControlleri „przesunięcie palcem od lewej krawędzi” w celu zainicjowania wyskoczenia widoku. viewWillAppearZostanie wywołana dla widoku, do którego są popping, ale jeśli anulować że „przesuń od lewej krawędzi”, aby powrócić do widoku z którego rozpoczął to okienko gest, pop zostaje anulowana, a viewDidAppearna widok zacząłeś Pop z powrotem nigdy nie zostanie wywołany.

    Efektem netto tego jest to, że powinieneś uważać, aby nie pisać kodu, który zakłada, że ​​po każdym wywołaniu do viewWillAppearnastąpi ostatecznie wywołanie do viewDidAppear. Jeśli przejście zostanie anulowane, tak się nie stanie.

Obrabować
źródło
5

viewwillappear wywoła przed załadowaniem widoku, abyś mógł wykonać określone zadanie przed załadowaniem tego widoku, a viewdidappear zostanie wywołany po załadowaniu widoku, więc zadanie wysyłania zostanie wykonane w tej metodzie

dks1725
źródło
4

Różnica między "will" i "did" ... Jak sama nazwa wskazuje, viewWillAppear jest wywoływana przed pojawieniem się widoku, a viewDidAppear jest wywoływana, gdy widok się pojawił.

Mahesh
źródło
spójrz na zaakceptowaną odpowiedź, która zawiera ponad 70 głosów za. :)
PJR
4

1) ViewWillAppear : Widok załadowany faktycznie do pamięci, wywołany raz w kontrolerze widoku i miał swoją ramkę, ale nadal nie pojawił się dla użytkownika

2) ViewDidAppear : Kontroler został dodany do hierarchii widoków, dzięki czemu można było zaprezentować następnemu kontrolerowi, również widok miał układ podwidoków

Abuzeid Ibrahim
źródło
3

To pierwsze dzieje się przed pojawieniem się widoku, a drugie dzieje się później.

Marc Abramowitz
źródło
3

Podsumowując:

-viewWillAppear -> aktualizuj dane (przeładuj dane z widoku tabeli)

-viewDidAppear -> kosztowne operacje (wywołanie API z niezłym postępem!)

Nahuel Roldan
źródło
1

Jak sama nazwa wskazuje, viewWillAppearjest wywoływana przed pojawieniem się widoku i viewDidAppearjest wywoływana, gdy widok się pojawił.

visakh7
źródło
0

Przykład zastosowania , tj. Kiedy należy użyć którego?

viewDidLoad - kiedy etykiety, przyciski (tj. dowolne kontrolki / podglądy) są podłączone do pliku interfejsu Widoku i jeśli chcesz załadować je wszystkie w tym samym czasie co Widok ViewControllera i jeśli chcesz załadować to raz do pamięci i być skończone z tym

viewWillAppear- powiedzmy, że chcesz zmienić kolor tła widoku za każdym razem, gdy viewController pojawi się na ekranie. Lub bardziej realistycznie, jeśli chcesz mieć kolor tła DarkMode w nocy w ciągu dnia i jasny kolor widoku tła w ciągu dnia, przejdź do tego kodu wviewWillAppear

Kolejny dobry przypadek użycia tutaj https://stackoverflow.com/a/39395865/5438240

Zauważ również, że jeśli używasz Navigation stack ( UINavigationController), viewWillDisappear()viewController, który ma zostać pobrany, ma wywołanie, a ViewController, który będzie następny na szczycie stosu, będzie viewWillAppear()wywoływał

Naishta
źródło