UIViewController viewDidLoad vs. viewWillAppear: Jaki jest właściwy podział pracy?

164

Zawsze byłem nieco niejasny od rodzaju zadań, które powinny być przypisane do viewDidLoadwersetach viewWillAppear: w UIViewControllerpodklasie.

np. robię aplikację, w której UIViewControllerpodklasa trafia na serwer, pobieram dane, przesyłam je do widoku, a następnie wyświetlam ten widok. Jakie są wady i zalety robienia tego w viewDidLoadvs. viewWillAppear?

dugla
źródło

Odpowiedzi:

251

viewDidLoad to rzeczy, które musisz zrobić raz. ViewWillAppear jest wywoływana za każdym razem, gdy pojawia się widok. Powinieneś robić rzeczy, które musisz zrobić tylko raz w viewDidLoad - na przykład ustawianie tekstów UILabel. Możesz jednak chcieć zmodyfikować określoną część widoku za każdym razem, gdy użytkownik go zobaczy, np. Aplikacja iPoda przewija teksty z powrotem na górę za każdym razem, gdy przejdziesz do widoku „Teraz odtwarzane”.

Jednak kiedy ładujesz rzeczy z serwera, musisz również pomyśleć o opóźnieniu. Jeśli spakujesz całą komunikację sieciową do viewDidLoad lub viewWillAppear, zostaną one wykonane, zanim użytkownik zobaczy widok - może to spowodować krótkie zawieszenie aplikacji. Dobrym pomysłem może być najpierw pokazanie użytkownikowi niezamieszkałego widoku z jakimś wskaźnikiem aktywności. Po zakończeniu pracy w sieci, co może zająć sekundę lub dwie (lub może nawet zawieść - kto wie?), Możesz wypełnić widok swoimi danymi. Dobre przykłady tego, jak można to zrobić, można zobaczyć w różnych klientach Twittera. Na przykład, gdy przeglądasz stronę szczegółów autora w serwisie Twitterrific, widok mówi tylko „Ładowanie ...”, dopóki zapytania sieciowe nie zostaną zakończone.

LeonBruksela
źródło
Tak więc, biorąc pod uwagę możliwość wielokrotnego wywoływania viewWillAppear. Czy ta metoda uruchomiłaby się, gdyby na przykład widok kontrolerów widoku stał się widoczny po ukryciu (mam na myśli zasłonięcie, a nie ukrytą metodę na UIView). W jakim scenariuszu wywołanie viewWillAppear bez poprzedzonego wywołania viewDidLoad?
dugla
7
viewDidLoad jest wywoływana TYLKO podczas konstruowania widoku - na przykład po wywołaniu kontrolera widoku initFromNibNamed podczas uzyskiwania dostępu do widoku. ViewWillAppear jest wywoływane za każdym razem, gdy kontroler widoku nie był widoczny, ale pojawia się - więc gdy kontroler widoku jest wciśnięty, wywoływana jest metoda viewWillAppear. Jeśli przesuniesz stamtąd inny widok podrzędny, a użytkownik wróci, ponownie zostanie wywołana funkcja viewWillAppear.
Kendall Helmstetter Gelner
Dzięki Kendall. Tak, kilka strategicznie rozmieszczonych NSLogs mnie posortowało. viewWillAppear / viewWillDissappear ogień po naciśnięciu / wyskoku kontrolera widoku.
dugla
3
Zauważ, że viewDidLoad zostanie RÓWNIEŻ wywołany, jeśli widok jest ukryty, a następnie rozładowany z powodów związanych z pamięcią, po czym pojawia się ponownie. Na co możesz liczyć: viewDidLoad zostanie wywołany PRZYNAJMNIEJ RAZ, gdy widok zostanie utworzony po raz pierwszy i MOŻLIWE więcej razy, gdy widok pojawi się ponownie po ukryciu. viewWillAppear będzie ZAWSZE wywoływana, gdy widok ma się pojawić na ekranie.
DanM
2
Czy ktoś może skomentować dalej te dwa powiązane pytania: (1) Czasami, nie zawsze, wartości ramek dla kontrolek (tj. Pochodzenie i rozmiar) są zerowe w viewDidLoad, a czasami nie - Dlaczego? (2) W szablonie firmy Apple dla detailView splitViewControllera (iPad) jest metoda configureView - co powinno się tam znaleźć względem viewDidLoad i ViewWillAppear?
Jeff
12

Początkowo używany tylko ViewDidLoad z tableView. Podczas testów z utratą Wi-Fi, ustawiając urządzenie w trybie samolotowym, zdałem sobie sprawę, że stół nie odświeżył się po powrocie Wi-Fi. W rzeczywistości wydaje się, że nie ma sposobu, aby odświeżyć tableView na urządzeniu, nawet naciskając przycisk home z trybem tła ustawionym na TAK w -Info.plist.

Moje rozwiązanie:

-(void) viewWillAppear: (BOOL) animated { [self.tableView reloadData];}
Jaminyah
źródło
10

Należy zauważyć, że używanie viewDidLoad do pozycjonowania jest nieco ryzykowne i należy go unikać, ponieważ granice nie są ustawione. może to spowodować nieoczekiwane rezultaty (miałem różne problemy ...)

Ten post dość dobrze opisuje różne metody i to, co dzieje się w każdej z nich.

obecnie do jednorazowego initowania i pozycjonowania myślę o użyciu viewDidAppear z flagą, jeśli ktoś ma jakieś inne zalecenia, daj mi znać.

keisar
źródło
zgadzam się z tym: "... należy unikać, ponieważ granice nie są ustalone ..."
danisupr4
4

Zależy, czy chcesz, aby dane były ładowane za każdym razem, gdy otwierasz widok? czy tylko raz ?

wprowadź opis obrazu tutaj

  • Czerwony: Nie wymagają zmiany za każdym razem. Po załadowaniu pozostają takie, jakie były.
  • Fioletowy: Muszą się zmieniać w czasie lub po każdym załadowaniu. Nie chcesz widzieć tych samych 3 sugerowanych użytkowników do obserwowania, musisz je ładować ponownie za każdym razem, gdy wrócisz do ekranu. Ich zdjęcia mogą się zaktualizować ... nie chcesz oglądać zdjęcia sprzed 5 lat ...

viewDidLoad:Cokolwiek masz do przetworzenia, musisz to zrobić raz.
viewWilLAppear:Niezależnie od przetwarzania, które musi się zmieniać za każdym razem, gdy strona jest ładowana.

Etykiety, ikony, tytuły przycisków lub większość danychInputedByDeveloper zwykle się nie zmienia. Nazwy, zdjęcia, linki, stan przycisków, listy (tablice wejściowe dla tableViews lub collectionView) lub większość dataInputedByUser zwykle się zmienia.

kochanie
źródło
Fiolet byłby nazwany w widoku, ale nie wyglądałby na widoku
Alex Kornhauser,
@AlexKornhauser, jak to się nazywa? Mówię, viewWillAppearże możesz zapytać i sprawdzić najnowsze tweety. viewDidAppearjest na to za późno
kochanie,