Jaka jest różnica między -[UIViewController viewWillAppear:]
i -[UIViewController viewDidAppear:]
?
Jaka jest różnica między -[UIViewController viewWillAppear:]
i -[UIViewController viewDidAppear:]
?
Odpowiedzi:
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.
viewWillAppear
? Masz na myśli pobieranie przez sieć? Ale sugerujesz również pobieranie rzeczy w viewDidAppear
?
ViewDidAppear
, łatwo wprowadzisz użytkowników w błąd co do interfejsu użytkownika :)
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ń.
viewWillAppear
Metoda jest wywoływana przed załadowaniem rzeczywisty widok.
viewDidAppear
Metoda jest wywoływana, gdy widok jest już załadowany, i chcesz pokazać coś.
Kilka uwag:
viewDidLoad
Metoda jest wywoływana, gdy widok jest pierwsza instancja. IBOutlet
odniesienia są podłączane do czasu wywołania tego, ale nie wcześniej. Jednak frame
widok 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ę frame
wartości na podstawie wymiarów widoku głównego, konfigurację tych ramek należy odłożyć do viewWillAppear
lub viewDidLayoutSubviews
.
viewWillAppear
Metoda 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, viewWillDisappear
jest oczywiście nazywany, gdy zaczyna się przejście od tego widoku.
viewDidAppear
Metoda jest wywoływana, gdy przedstawienie widoku odbywa się, w szczególności, gdy wszelkie związane animacja została zakończona. Jego towarzysz, viewDidDisappear
jest oczywiście nazywany, gdy następuje przejście od tego widoku.
Dwa ważne zastrzeżenia:
viewDidLoad
jest wywoływana raz i tylko raz, podczas pierwszego tworzenia wystąpienia widoku. Z drugiej strony, viewWillAppear
i viewDidAppear
bę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, viewWillAppear
i viewDidAppear
będzie generalnie wywoływany ponownie, gdy dany widok zostanie dodany i animowany z powrotem do hierarchii widoków, ale viewDidLoad
tak się nie stanie. viewDidLoad
jest 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 viewWillAppear
lub 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 viewWillAppear
nie 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ć. viewWillAppear
To znaczy , tylko dlatego, że jest wezwany, nie oznacza, że viewDidAppear
zostanie 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ę viewWillAppear
na „ viewMightAppear
albo viewWillProbablyAppear
, albo iReallyWishThisViewWouldAppear
”.
Przykładem wbudowanego gestu interaktywnego jest użycie a UINavigationController
i „przesunięcie palcem od lewej krawędzi” w celu zainicjowania wyskoczenia widoku. viewWillAppear
Zostanie 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 viewDidAppear
na 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 viewWillAppear
nastąpi ostatecznie wywołanie do viewDidAppear
. Jeśli przejście zostanie anulowane, tak się nie stanie.
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
To pierwsze dzieje się przed pojawieniem się widoku, a drugie dzieje się później.
Podsumowując:
-viewWillAppear -> aktualizuj dane (przeładuj dane z widoku tabeli)
-viewDidAppear -> kosztowne operacje (wywołanie API z niezłym postępem!)
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ł