Qual è la differenza tra -[UIViewController viewWillAppear:]e -[UIViewController viewDidAppear:]?
Qual è la differenza tra -[UIViewController viewWillAppear:]e -[UIViewController viewDidAppear:]?
Risposte:
In generale, questo è quello che faccio:
1) ViewDidLoad - Ogni volta che aggiungo controlli a una vista che dovrebbe apparire insieme alla vista, subito, la inserisco nel metodo ViewDidLoad. Fondamentalmente questo metodo viene chiamato ogni volta che la vista è stata caricata in memoria. Ad esempio, se la mia vista è un modulo con 3 etichette, aggiungerei le etichette qui; la vista non esisterà mai senza quelle forme.
2) ViewWillAppear : di solito utilizzo ViewWillAppear solo per aggiornare i dati nel modulo. Quindi, per l'esempio sopra, lo userei per caricare effettivamente i dati dal mio dominio nel modulo. La creazione di UIViews è piuttosto costosa e dovresti evitare il più possibile di farlo con il metodo ViewWillAppear, poiché quando viene chiamato, significa che l'iPhone è già pronto a mostrare l'UIView all'utente e qualsiasi cosa pesante fai qui avrà un impatto sulle prestazioni in modo molto visibile (come il ritardo delle animazioni, ecc.).
3) ViewDidAppear : Infine, utilizzo ViewDidAppear per iniziare nuovi thread su cose che richiederebbero molto tempo per essere eseguite, come ad esempio fare una chiamata al servizio web per ottenere dati extra per il modulo sopra. La cosa buona è che la vista esiste già e viene visualizzato all'utente, puoi mostrare un bel messaggio "In attesa" all'utente mentre ottieni i dati.
viewWillAppear? Intendi scaricare attraverso la rete? Ma suggerisci anche di scaricare contenuti in viewDidAppear?
ViewDidAppearconfonderai facilmente l'utente sull'interfaccia utente :)
viewDidLoad === >>> Inserisci qui il tuo codice di inizializzazione. Non inserire dati dinamici che potrebbero cambiare durante il ciclo di vita della vista. Quindi, se stai estraendo dati da dati core, non vuoi farlo qui se ciò potrebbe cambiare durante la vita della vista. Ad esempio: supponi di avere un controller per schede. Passa da tab1 a tab2 e cambi qualcosa sul modello in tab2. Se torni a tab1 e il codice del tuo modello è stato eseguito in viewDidLoad, questo non verrà aggiornato (supponendo che non stai usando KVO o NSFetchedResultsController, ecc.).
viewWillAppear === >>> Questo viene chiamato ogni volta che la vista sta per apparire, indipendentemente dal fatto che la vista sia già in memoria. Inserisci qui il tuo codice dinamico, come la logica del modello.
viewDidAppear === >>> Metti qui le operazioni costose che vuoi fare solo se sei sicuro che la vista sia sullo schermo, come le chiamate di rete.
Avviso: se l'app è in background e torna in primo piano, è necessario gestirla utilizzando NSNotificationCenter. Ho scritto il codice per quello nei commenti qui sotto. Potresti pensare che viewWillAppear / viewDidAppear si attivi. Metti lì un punto di interruzione e testalo. Non spara. Quindi, se qualcosa è cambiato per la tua app mentre era in background, dovrai aggiornarla utilizzando le notifiche.
Il viewWillAppearmetodo viene chiamato prima di caricare la vista effettiva.
Il viewDidAppearmetodo viene chiamato quando la vista è già caricata e si desidera mostrare qualcosa.
viewWillAppear:
■ Chiamato prima che la vista venga aggiunta alla gerarchia della vista di Windows
■ Chiamata prima di [vc.view layoutSubviews] (se necessario)
viewDidAppear :
■ Chiamata dopo che la vista è stata aggiunta alla gerarchia della vista
■ Chiamata dopo [vc.view layoutSubviews] (se necessario)
Alcune osservazioni:
Il viewDidLoadmetodo viene chiamato alla prima istanza della vista. IBOutleti riferimenti sono collegati quando è stato chiamato, ma non prima. Tuttavia, framela vista potrebbe non essere stabilita al momento della chiamata. Questo è un ottimo posto per aggiungere / configurare viste secondarie e i loro vincoli associati. Ma se stai eseguendo una configurazione manuale dei framevalori sulla base delle dimensioni della vista principale, la configurazione di quei frame dovrebbe essere rinviata fino a viewWillAppearo viewDidLayoutSubviews.
Il viewWillAppearmetodo viene chiamato quando la presentazione della vista nella gerarchia della vista sta per iniziare. In particolare, questo viene chiamato all'inizio dell'animazione (se presente) della presentazione della vista. Il suo compagno, viewWillDisappearovviamente , viene chiamato quando inizia la transizione da questa visione.
Il viewDidAppearmetodo viene chiamato al termine della presentazione della vista, in particolare al termine di tutte le animazioni associate. Il suo compagno, viewDidDisappearovviamente , viene chiamato al termine della transizione da questa visione.
Due avvertenze importanti:
viewDidLoadviene chiamato una volta e una sola volta, quando la vista viene istanziata per la prima volta. D'altra parte, viewWillAppeare viewDidAppearverrà chiamato non solo quando la vista viene presentata per la prima volta, ma ogni volta successiva viene riproposta la stessa vista in questione. Ad esempio, quando si presenta per la prima volta una vista, verranno chiamati tutti e tre questi metodi. Se la vista in questione presenta successivamente un'altra vista che viene successivamente respinta, viewWillAppeare viewDidAppearverrà generalmente nuovamente richiamata quando la vista in questione viene aggiunta e animata nuovamente nella gerarchia della vista, ma viewDidLoadnon lo farà. viewDidLoadviene chiamato solo quando questa istanza particolare viene creata per la prima volta.
Quindi, se vuoi fare qualcosa ogni volta che riappare una vista (ad es. Scartare o tornare ad essa), fallo in viewWillAppearo viewDidAppear. Se vuoi che accada solo quando la vista viene istanziata per la prima volta, fallo viewDidLoad.
La chiamata di viewWillAppearnon garantisce che la transizione a quella vista sarà mai completata. In particolare, se si utilizza una transizione interattiva guidata dall'input dell'utente in tempo reale, ma tale transizione interattiva può essere annullata. Cioè, solo perché viewWillAppearviene chiamato, non significa che viewDidAppearverrà chiamato. Generalmente lo è, ma se il gesto interattivo viene annullato, non lo farà (perché la transizione non è mai terminata).
Al WWDC 2013, nel contesto delle transizioni interattive, un presentatore ha scherzato sul fatto che avrebbero dovuto rinominare viewWillAppear" viewMightAppear, o viewWillProbablyAppear, o iReallyWishThisViewWouldAppear".
Un esempio di gesto interattivo incorporato è quando si usa a UINavigationControllere si "scorre dal bordo sinistro" per avviare un pop della vista. La viewWillAppearsi chiamerà per la vista a cui si stanno spuntando, ma se si annulla che "scorri da un lato di sinistra" per tornare indietro alla vista da cui è stato avviato questo gesto pop, pop viene annullata e la viewDidAppearper la vista che si ha iniziato a il pop-back non verrà mai chiamato.
L'effetto netto di questo è che dovresti stare attento a non scrivere codice che presume che ogni chiamata a viewWillAppearsarà seguita alla fine da una chiamata a viewDidAppear. Se la transizione viene annullata, non sarà così.
1) ViewWillAppear : la vista caricata effettivamente nella memoria, chiamata una volta nel controller della vista e aveva il suo frame, ma non appariva ancora all'utente
2) ViewDidAppear : il controller è stato aggiunto alla gerarchia della vista, in modo da poter presentare al controller successivo, inoltre, la vista ha fatto il layout delle sottoview
Il primo accade prima che appaia la vista e il secondo accade dopo.
Per riassumere:
-viewWillAppear -> aggiorna i dati (ricarica i dati da una vista tabella)
-viewDidAppear -> operazioni costose (chiamata API con un bel progresso hud!)
Usecase , cioè quando dovrei usare quale?
viewDidLoad - quando etichette, pulsanti (i, e qualsiasi controllo / sottoview) sono collegati al file di interfaccia di View e se si desidera caricarli tutti contemporaneamente come View ViewController, e se si desidera caricare questo in memoria una volta ed essere fatto con esso
viewWillAppear- diciamo, vuoi cambiare il colore di sfondo della vista ogni volta che viewController appare sullo schermo. O più realisticamente se vuoi il colore di sfondo di DarkMode durante le ore notturne del giorno e il colore chiaro della vista di sfondo durante il giorno, cerca questo codice inviewWillAppear
Un altro buon esempio qui https://stackoverflow.com/a/39395865/5438240
Si noti inoltre che, se si utilizza uno stack di navigazione ( UINavigationController), il viewController che sta per essere espulso ha il viewWillDisappear()chiamato e il ViewController che sarà successivamente in cima allo stack avrà viewWillAppear()chiamato