Cerca di capire il ciclo di vita di iOS UIViewController


299

Potresti spiegarmi il modo corretto di gestire il UIViewControllerciclo di vita?

In particolare, vorrei sapere come utilizzare Initialize, ViewDidLoad, ViewWillAppear, ViewDidAppear, ViewWillDisappear, ViewDidDisappear, ViewDidUnloade Disposemetodi in Mono touch per una UIViewControllerclasse.


Ci sono alcune informazioni o collegamenti per OSX ViewController e WindowController? Per favore, condividilo.
Anoop Vaidya,

Risposte:


410

Tutti questi comandi vengono chiamati automaticamente da iOS al momento opportuno quando si carica / presenta / nasconde il controller di visualizzazione. È importante notare che questi metodi sono collegati UIViewControllere non a UIViewse stessi. Non otterrai nessuna di queste funzionalità solo usando a UIView.

C'è un'ottima documentazione sul sito di Apple qui . Inserendo semplicemente però:

  • ViewDidLoad- Chiamato quando si crea la classe e si carica da xib. Ottimo per la configurazione iniziale e per il lavoro una tantum.

  • ViewWillAppear- Chiamato proprio prima che appaia la vista, ottimo per nascondere / mostrare campi o qualsiasi operazione che si desidera eseguire ogni volta che la vista è visibile. Poiché potresti passare da una vista all'altra, questa verrà chiamata ogni volta che la tua vista sta per apparire sullo schermo.

  • ViewDidAppear - Chiamato dopo la visualizzazione della vista - ottimo posto per avviare animazioni o il caricamento di dati esterni da un'API.

  • ViewWillDisappear/ DidDisappear- Stessa idea di ViewWillAppear/ ViewDidAppear.

  • ViewDidUnload/ ViewDidDispose- In Objective-C, è qui che fai la pulizia e il rilascio delle cose, ma questo viene gestito automaticamente, quindi non c'è molto da fare qui.


86
Questo testo è leggermente fuorviante, poiché ViewDidLoad non deve essere utilizzato per il lavoro singolo. Potrebbe essere chiamato più volte se la vista viene scaricata a causa della memoria insufficiente e quindi caricata di nuovo.
Ricky Helgesson,

4
ViewDidLoad non viene effettivamente chiamato quando si crea / inizializza il controller di visualizzazione. Si chiama la prima volta che si fa qualsiasi cosa vista relativa alla vista del controller di visualizzazione. Come aggiungerlo come sottoview, impostare la cornice, ecc. Viene anche chiamato ovviamente quando si carica da un pennino.
Jason Grandelli,

3
ViewDidAppear - Chiamato dopo la visualizzazione della vista - ottimo posto per iniziare un'animazione o il caricamento di dati esterni da un'API. Perché è un buon posto per iniziare a caricare i dati? Perché non viewDidLoad?
Anton Chikin,

1
che dire del metodo loadView, se viene chiamato la prima volta quando un pennino viene caricato in memoria prima di viewDidLoad o no.
iHulk,

@chakrit questo è un buon punto - viewDidAppear è un ottimo posto per aggiornare i dati (se necessario). Non sono d'accordo su KVO, perché può causare aggiornamenti indesiderati sulle visualizzazioni che non vengono mai effettivamente visualizzate da un utente.
Anton Chikin,

409

AGGIORNAMENTO: ViewDidUnload è stato deprecato in iOS 6, quindi aggiornato la risposta di conseguenza.

Il ciclo di vita di UIViewController è rappresentato qui:

Ciclo di vita di un controller di visualizzazione, schematizzato

Il vantaggio dell'utilizzo di Xamarin Native / Mono Touch è che utilizza le API native e quindi segue lo stesso ciclo di vita di ViewController come si trova nella documentazione di Apple.


17
Dove vanno visualizzati ViewWillLayoutSubviews e viewDidLayoutSubviews in questo diagramma di flusso?
Max_Power89

7
Questo diagramma non è preciso. viewDidUnload è deprecata dal iOS6: stackoverflow.com/questions/12509102/...
occulus

2
Questo è davvero semplicemente sbagliato . Un altro esempio di risposta semplicemente sbagliata su SO, col passare degli anni. Il calcolo è altamente non statico.
Fattie,

186

Questo è per le ultime versioni di iOS (modificato con Xcode 9.3, Swift 4.1 ). Di seguito sono riportate tutte le fasi che rendono UIViewControllercompleto il ciclo di vita .

  • loadView()

  • loadViewIfNeeded()

  • viewDidLoad()

  • viewWillAppear(_ animated: Bool)

  • viewWillLayoutSubviews()

  • viewDidLayoutSubviews()

  • viewDidAppear(_ animated: Bool)

  • viewWillDisappear(_ animated: Bool)

  • viewDidDisappear(_ animated: Bool)

Lasciami spiegare tutte quelle fasi.

1. loadView

Questo evento crea / carica la vista gestita dal controller. Può caricare da un file pennino associato o vuoto UIViewse è stato trovato null. Questo lo rende un buon posto per creare le tue visualizzazioni in codice a livello di codice.

È qui che le sottoclassi dovrebbero creare la loro gerarchia di viste personalizzate se non usano un pennino. Non dovrebbe mai essere chiamato direttamente. Sostituisci questo metodo solo quando crei visualizzazioni a livello di viewcodice e assegni la vista root alla proprietà Non chiamare il metodo super quando esegui l' override di LoadView

2. loadViewIfNeeded

Se in caso la vista della corrente viewControllernon è stata ancora impostata, questo metodo caricherà la vista ma ricorda, questo è disponibile solo in iOS> = 9.0. Quindi, se stai supportando iOS <9.0, non aspettarti che arrivi in ​​figura.

Carica la vista del controller di visualizzazione se non è già stata impostata.

3. viewDidLoad

L' viewDidLoadevento viene chiamato solo quando la vista viene creata e caricata in memoria ma i limiti per la vista non sono ancora definiti. Questo è un buon posto per inizializzare gli oggetti che il controller di visualizzazione utilizzerà.

Chiamato dopo che la vista è stata caricata. Per i controller di visualizzazione creati nel codice, questo è dopo -loadView. Per i controller di vista non archiviati da un pennino, ciò avviene dopo aver impostato la vista.

4. viewWillAppear

Questo evento avvisa viewControllerogni volta che la vista appare sullo schermo. In questo passaggio la vista ha limiti definiti ma l'orientamento non è impostato.

Chiamato quando la vista sta per essere resa visibile. L'impostazione predefinita non fa nulla.

5. viewWillLayoutSubviews

Questo è il primo passo nel ciclo di vita in cui i limiti sono finalizzati. Se non si utilizzano vincoli o layout automatico, è probabile che si desideri aggiornare qui le visualizzazioni secondarie. Questo è disponibile solo in iOS> = 5.0. Quindi, se stai supportando iOS <5.0, non aspettarti che entrerà in scena.

Chiamato poco prima che venga invocato il metodo layoutSubviews della vista del controller di visualizzazione. Le sottoclassi possono essere implementate secondo necessità. L'impostazione predefinita è no.

6. viewDidLayoutSubviews

Questo evento notifica al controller di visualizzazione che sono state impostate le visualizzazioni secondarie. È un buon posto per apportare modifiche alle visualizzazioni secondarie dopo che sono state impostate. Questo è disponibile solo in iOS> = 5.0. Quindi, se stai supportando iOS <5.0, non aspettarti che entrerà in scena.

Chiamato subito dopo il richiamo del metodo layoutSubviews della vista del controller di visualizzazione. Le sottoclassi possono essere implementate secondo necessità. L'impostazione predefinita è no.

7. viewDidAppear

L' viewDidAppearevento si attiva dopo che la vista è stata visualizzata sullo schermo. Il che lo rende un buon posto per ottenere dati da un servizio o database di back-end.

Chiamato quando la vista è stata completamente trasferita sullo schermo. L'impostazione predefinita non fa nulla

8. viewWillDisappear

L' viewWillDisappearevento si attiva quando la vista di presentazione viewControllersta per scomparire, respingere, coprire o nascondersi dietro l'altro viewController. Questo è un buon posto dove puoi limitare le tue chiamate di rete, invalidare il timer o rilasciare oggetti che sono legati a questo viewController.

Chiamato quando la vista viene ignorata, coperta o altrimenti nascosta.

9. viewDidDisappear

Questo è l'ultimo passaggio del ciclo di vita a cui chiunque può rivolgersi mentre questo evento si attiva subito dopo che la vista di presentazione viewControllerè scomparsa, respinta, coperta o nascosta.

Chiamato dopo che la vista è stata respinta, coperta o altrimenti nascosta. L'impostazione predefinita non fa nulla

Ora come per Apple quando stai implementando questo metodo, dovresti ricordare di chiamare l' superimplementazione di quel metodo specifico.

Se si esegue la sottoclasse di UIViewController, è necessario chiamare la super implementazione di questo metodo, anche se non si utilizza un NIB. (Per comodità, il metodo init predefinito lo farà per te e specificherà zero per entrambi gli argomenti di questo metodo.) Nella NIB specificata, il proxy Proprietario del file dovrebbe avere la sua classe impostata sulla sottoclasse del controller di visualizzazione, con il punto di vista view collegato alla vista principale. Se invochi questo metodo con un nome nib nib, il -loadViewmetodo di questa classe tenterà di caricare un NIB il cui nome è lo stesso della classe del controller di visualizzazione. Se in realtà non esiste un NIB di questo tipo, è necessario chiamare -setView:prima che -viewsia invocato o sostituire il -loadViewmetodo per impostare le visualizzazioni in modo programmatico.

Spero che questo abbia aiutato. Grazie.

UPDATE - Come @ThomasW indicato all'interno commento viewWillLayoutSubviewse viewDidLayoutSubviewssarà anche chiamato in altri momenti in cui subviews di vista principale vengono caricati, ad esempio quando le cellule di una vista tabella o vista raccolta vengono caricati.

AGGIORNAMENTO - Come indicato da @Maria all'interno del commento, la descrizione di è loadViewstata aggiornata


6
viewWillLayoutSubviewse viewDidLayoutSubviewsverrà anche chiamato altre volte quando vengono caricate le viste secondarie della vista principale, ad esempio quando vengono caricate le celle di una vista tabella o vista raccolta.
ThomasW,

C'è una leggera fuorviante in questa risposta: loadView () viene sempre chiamato, non dovrebbe essere sovrascritto quando la vista per il controller è stata creata in IB.
Maria,

@Maria Per favore, vai avanti e modifica la risposta se pensi che possa essere migliorata. Grazie.
onCompletion,

L'impostazione predefinita non fa nulla di sbagliato viewWillAppear viewDidAppear viewDidDisappear. Devi chiamare super ad un certo punto.
Mick,

47

iOS 10,11 (Swift 3.1, Swift 4.0)

Secondo UIViewControllera UIKitsviluppatori,

1. loadView ()

È qui che le sottoclassi dovrebbero creare la loro gerarchia di viste personalizzate se non usano un pennino . Non dovrebbe mai essere chiamato direttamente.

2. loadViewIfNeeded ()

Carica la vista del controller di visualizzazione se non è già stata impostata.

3. viewDidLoad ()

Chiamato dopo che la vista è stata caricata. Per i controller di visualizzazione creati nel codice, questo è dopo -loadView. Per i controller di vista non archiviati da un pennino, ciò avviene dopo aver impostato la vista.

4. viewWillAppear (_ animato: Bool)

Chiamato quando la vista sta per essere resa visibile. L'impostazione predefinita non fa nulla

5. viewWillLayoutSubviews ()

Chiamato poco prima che venga invocato il metodo layoutSubviews della vista del controller di visualizzazione. Le sottoclassi possono essere implementate secondo necessità. L'impostazione predefinita non fa nulla.

6. viewDidLayoutSubviews ()

Chiamato subito dopo il richiamo del metodo layoutSubviews della vista del controller di visualizzazione. Le sottoclassi possono essere implementate secondo necessità. L'impostazione predefinita non fa nulla.

7. viewDidAppear (_ animato: Bool)

Chiamato quando la vista è stata completamente trasferita sullo schermo. L'impostazione predefinita non fa nulla

8. viewWillDisappear (_ animato: Bool)

Chiamato quando la vista viene ignorata, coperta o altrimenti nascosta. L'impostazione predefinita non fa nulla

9. viewDidDisappear (_ animato: Bool )

Chiamato dopo che la vista è stata respinta, coperta o altrimenti nascosta. L'impostazione predefinita non fa nulla

10. viewWillTransition (su misura: CGSize, con coordinatore: UIViewControllerTransitionCoordinator)

Chiamato quando la vista è in transizione.

11. willMove (toParentViewController parent: UIViewController?)

12. didMove (toParentViewController parent: UIViewController?)

Questi due metodi sono pubblici per le sottoclassi dei container da chiamare durante la transizione tra controller figlio. Se vengono sostituiti, gli override dovrebbero assicurarsi di chiamare il super.

L'argomento genitore in entrambi questi metodi è nullo quando un figlio viene rimosso dal suo genitore; altrimenti è uguale al nuovo controller della vista padre.

13. didReceiveMemoryWarning ()

Chiamato quando l'applicazione padre riceve un avviso di memoria. Su iOS 6.0 non cancella più la vista per impostazione predefinita.


2
È davvero ovvio che stackoverflow non eliminerà tutte le risposte errate e incomplete da questo intero thread. La tua risposta sembra completa per quanto riguarda le chiamate di metodo, quindi suppongo che la tua sia corretta e lavorerò su quello.
Logicsaurus Rex,

Che cos'è un nibcome menzionato sotto loadView?
Petrus Theron,

2
@LogicsaurusRex Sono d'accordo. Allo stesso modo in cui SO contrassegna le domande come duplicate o protette, penso che dovrebbe essere in grado di contrassegnare le risposte come obsolete o obsolete
rmp251

Il punto 5 sopra è errato. viewWillLayoutSubviews()viene chiamato prima che l'oggetto layoutSubviews()
viewController

28

A partire da iOS 6 e versioni successive. Il nuovo diagramma è il seguente:

inserisci qui la descrizione dell'immagine


1
Chiama quella vista "A". Considera una seconda vista "B" che appare mentre "A" scompare. "B.viewWillAppear" è prima o dopo "A.viewDidDisappear"? E ci sono situazioni in cui cambia l'ordine di quei due?
ToolmakerSteve

Sembra che la nuova vista (B) willApear verrà chiamata prima che scompaia. Per la seconda domanda Ho bisogno di un po 'di tempo per esaminarlo.
Saad,

21

Concentriamoci sui metodi, che sono responsabili del ciclo di vita di UIViewController :

  • Creazione:

    - (void)init

    - (void)initWithNibName:

  • Visualizza la creazione:

    - (BOOL)isViewLoaded

    - (void)loadView

    - (void)viewDidLoad

    - (UIView *)initWithFrame:(CGRect)frame

    - (UIView *)initWithCoder:(NSCoder *)coder

  • Gestione del cambio di stato della vista:

    - (void)viewDidLoad

    - (void)viewWillAppear:(BOOL)animated

    - (void)viewDidAppear:(BOOL)animated

    - (void)viewWillDisappear:(BOOL)animated

    - (void)viewDidDisappear:(BOOL)animated

    - (void)viewDidUnload

  • Gestione degli avvisi di memoria:

    - (void)didReceiveMemoryWarning

  • deallocazione

    - (void)viewDidUnload

    - (void)dealloc

Diagramma del ciclo di vita di UIViewController

Per ulteriori informazioni, consultare il riferimento alla classe UIViewController .


19

I metodi viewWillLayoutSubviewse viewDidLayoutSubviewsnon sono menzionati nei diagrammi, ma questi sono chiamati tra viewWillAppeare viewDidAppear. Possono essere chiamati più volte.


Verranno inoltre chiamati altre volte quando vengono caricate le viste secondarie della vista principale, ad esempio quando vengono caricate le celle di una vista tabella o vista raccolta.
ThomasW,

16

La risposta di Haider è corretta per pre-iOS 6. Tuttavia, a partire da iOS 6 viewDidUnload e viewWillUnload non vengono mai chiamati. Il documento dichiara: "Le viste non vengono più eliminate in condizioni di memoria insufficiente e quindi questo metodo non viene mai chiamato."


Ho provato a mettere un punto di interruzione in ViewWillDisappear, ViewDidDisappear, Dispose. Ma nessuno di loro veniva invocato quando navigavo con il metodo PresentViewController (). Quale potrebbe essere la ragione?
Sreeraj,

1
Il collegamento non funziona ... Quindi cosa fa il sistema operativo con memoria insufficiente?
Figlio,

Li salva su disco?
Ian Warburton,

16

Ci sono molte informazioni obsolete e incomplete qui. Solo per iOS 6 e versioni successive :

  1. loadView[un]
  2. viewDidLoad[un]
  3. viewWillAppear
  4. viewWillLayoutSubviews è il primo limite di tempo finalizzato
  5. viewDidLayoutSubviews
  6. viewDidAppear
  7. * viewWillLayoutSubviews[B]
  8. * viewDidLayoutSubviews[B]

Note:

(a) - Se annulli manualmente la visualizzazione durante didReceiveMemoryWarning,loadView e viewDidLoadsarà chiamato di nuovo. Cioè, per impostazione predefinita loadViewe viewDidLoadviene chiamato solo una volta per istanza del controller di visualizzazione.

(b) Può essere chiamato altre 0 o più volte.


1
viewWillLayoutSubviewse viewDidLayoutSubviewsverrà anche chiamato altre volte quando vengono caricate le viste secondarie della vista principale, ad esempio quando vengono caricate le celle di una vista tabella o vista raccolta.
ThomasW,


0

Secondo il documento di Apple - Inizia a sviluppare app iOS (Swift) - Lavora con i controller di visualizzazione - Comprendi il ciclo di vita dei controller di visualizzazione

viewDidLoad(): Chiamato quando la vista del contenuto del controller di visualizzazione (la parte superiore della gerarchia della vista) viene creata e caricata da uno storyboard. ... Utilizzare questo metodo per eseguire qualsiasi configurazione aggiuntiva richiesta dal controller della vista.

viewWillAppear(): Chiamato appena prima della visualizzazione del contenuto del controller di visualizzazione nella gerarchia di visualizzazione dell'app. Utilizzare questo metodo per attivare tutte le operazioni che devono verificarsi prima che la visualizzazione del contenuto venga visualizzata sullo schermo

viewDidAppear(): Chiamato subito dopo l'aggiunta della vista contenuto del controller di visualizzazione alla gerarchia di visualizzazione dell'app. Utilizzare questo metodo per attivare tutte le operazioni che devono verificarsi non appena la vista viene visualizzata sullo schermo, come il recupero dei dati o la visualizzazione di un'animazione.

viewWillDisappear(): Chiamato appena prima che la vista del contenuto del controller di visualizzazione venga rimossa dalla gerarchia di visualizzazione dell'app. Utilizzare questo metodo per eseguire attività di pulizia come eseguire modifiche o dimettersi dal primo stato di risposta.

viewDidDisappear(): Chiamato subito dopo che la vista del contenuto del controller di visualizzazione è stata rimossa dalla gerarchia di visualizzazione dell'app. Utilizzare questo metodo per eseguire ulteriori attività di smontaggio.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.