Sie möchten den Lebenszyklus von iOS UIViewController verstehen

299

Können Sie mir die richtige Art und Weise erklären, den UIViewControllerLebenszyklus zu verwalten ?

Insbesondere würde ich gerne wissen , wie zu verwenden Initialize, ViewDidLoad, ViewWillAppear, ViewDidAppear, ViewWillDisappear, ViewDidDisappear, ViewDidUnloadund DisposeMethoden in Mono - Touch für eine UIViewControllerKlasse.

Lorenzo B.
quelle
Gibt es Informationen oder Links zu OSX ViewController und WindowController? Bitte teile es.
Anoop Vaidya

Antworten:

410

Alle diese Befehle werden von iOS zu den entsprechenden Zeiten automatisch aufgerufen, wenn Sie den View Controller laden / präsentieren / ausblenden. Es ist wichtig zu beachten, dass diese Methoden an sich selbst UIViewControllerund nicht an sich UIViewselbst gebunden sind . Sie erhalten keine dieser Funktionen nur mit a UIView.

Auf Apples Website finden Sie hier eine großartige Dokumentation . Einfach einfügen:

  • ViewDidLoad- Wird aufgerufen, wenn Sie die Klasse erstellen und aus xib laden. Ideal für die Ersteinrichtung und einmalige Arbeit.

  • ViewWillAppear- Wird direkt vor dem Anzeigen Ihrer Ansicht aufgerufen. Sie eignet sich zum Ausblenden / Anzeigen von Feldern oder für Vorgänge, die jedes Mal ausgeführt werden sollen, bevor die Ansicht sichtbar ist. Da Sie möglicherweise zwischen den Ansichten hin und her wechseln, wird dies jedes Mal aufgerufen, wenn Ihre Ansicht auf dem Bildschirm angezeigt wird.

  • ViewDidAppear - Wird aufgerufen, nachdem die Ansicht angezeigt wurde - ein großartiger Ort, um Animationen zu starten oder externe Daten von einer API zu laden.

  • ViewWillDisappear/ DidDisappear- Gleiche Idee wie ViewWillAppear/ ViewDidAppear.

  • ViewDidUnload/ ViewDidDispose- In Objective-C erledigen Sie hier Ihre Bereinigung und Freigabe von Dingen, aber dies wird automatisch erledigt, so dass Sie hier nicht viel tun müssen.

Jacob Knobel
quelle
86
Dieser Text ist leicht irreführend, da ViewDidLoad nicht für einmalige Arbeiten verwendet werden sollte. Es kann mehrmals aufgerufen werden, wenn die Ansicht aufgrund des geringen Arbeitsspeichers entladen und dann erneut geladen wird.
Ricky Helgesson
4
ViewDidLoad wird beim Erstellen / Initialisieren des View Controllers nicht aufgerufen. Es wird aufgerufen, wenn Sie zum ersten Mal eine Ansicht ausführen, die mit der Ansicht des Ansichtscontrollers zusammenhängt. Zum Beispiel als Unteransicht hinzufügen, den Rahmen einstellen usw. Es wird natürlich auch beim Laden von einer Feder aufgerufen.
Jason Grandelli
3
ViewDidAppear - Wird aufgerufen, nachdem die Ansicht angezeigt wurde - ein großartiger Ort, um Animationen zu starten oder externe Daten von einer API zu laden. Warum ist es ein guter Ort, um mit dem Laden von Daten zu beginnen? Warum nicht viewDidLoad?
Anton Chikin
1
Was ist mit der loadView-Methode, wenn sie zum ersten Mal aufgerufen wird, wenn eine Feder vor viewDidLoad in den Speicher geladen wird oder nicht?
iHulk
@chakrit Dies ist ein guter Punkt - viewDidAppear ist ein großartiger Ort, um Daten zu aktualisieren (falls erforderlich). Ich bin mit KVO nicht einverstanden, da dies zu unerwünschten Aktualisierungen der Ansichten führen kann, die von einem Benutzer niemals tatsächlich angezeigt werden.
Anton Chikin
409

UPDATE: ViewDidUnload war in iOS 6 veraltet, daher wurde die Antwort entsprechend aktualisiert.

Der UIViewController-Lebenszyklus ist hier dargestellt:

Der Lebenszyklus eines View Controllers ist grafisch dargestellt

Der Vorteil der Verwendung von Xamarin Native / Mono Touch besteht darin, dass die nativen APIs verwendet werden und daher derselbe ViewController-Lebenszyklus folgt, den Sie in der Apple-Dokumentation finden würden.

Haider
quelle
17
Wohin gehen viewWillLayoutSubviews und viewDidLayoutSubviews in diesem Flussdiagramm?
Max_Power89
7
Dieses Diagramm ist ungenau. viewDidUnload ist seit iOS6 veraltet: stackoverflow.com/questions/12509102/…
Occulus
2
Das ist in der Tat einfach falsch . Ein weiteres Beispiel für eine einfach falsche Antwort auf SO im Laufe der Jahre. Computing ist in hohem Maße nicht statisch.
Fattie
186

Dies gilt für die neuesten iOS-Versionen (geändert mit Xcode 9.3, Swift 4.1 ). Nachfolgend sind alle Phasen aufgeführt, die den Lebenszyklus eines UIViewControllervollständigen Lebenszyklus ausmachen .

  • loadView()

  • loadViewIfNeeded()

  • viewDidLoad()

  • viewWillAppear(_ animated: Bool)

  • viewWillLayoutSubviews()

  • viewDidLayoutSubviews()

  • viewDidAppear(_ animated: Bool)

  • viewWillDisappear(_ animated: Bool)

  • viewDidDisappear(_ animated: Bool)

Lassen Sie mich all diese Phasen erklären.

1. loadView

Dieses Ereignis erstellt / lädt die Ansicht, die der Controller verwaltet. Es kann aus einer zugeordneten NIB-Datei oder aus einer leeren Datei geladen werden, UIViewwenn null gefunden wurde. Dies macht es zu einem guten Ort, um Ihre Ansichten programmgesteuert im Code zu erstellen.

Hier sollten Unterklassen ihre benutzerdefinierte Ansichtshierarchie erstellen, wenn sie keine Schreibfeder verwenden. Sollte niemals direkt angerufen werden. Überschreiben Sie diese Methode nur, wenn Sie Ansichten programmgesteuert erstellen und die Stammansicht der viewEigenschaft zuweisen. Rufen Sie keine Super-Methode auf, wenn Sie loadView überschreiben

2. loadViewIfNeeded

Wenn die aktuelle Ansicht viewControllernoch nicht festgelegt wurde, lädt diese Methode die Ansicht. Beachten Sie jedoch, dass dies nur in iOS> = 9.0 verfügbar ist. Wenn Sie also iOS <9.0 unterstützen, erwarten Sie nicht, dass es ins Bild kommt.

Lädt die Ansicht des View Controllers, falls diese noch nicht festgelegt wurde.

3. viewDidLoad

Das viewDidLoadEreignis wird nur aufgerufen, wenn die Ansicht erstellt und in den Speicher geladen wird, die Grenzen für die Ansicht jedoch noch nicht definiert sind. Dies ist ein guter Ort, um die Objekte zu initialisieren, die der View Controller verwenden wird.

Wird aufgerufen, nachdem die Ansicht geladen wurde. Für im Code erstellte Ansichtscontroller ist dies nach -loadView. Bei Ansichtscontrollern, die nicht von einer Schreibfeder archiviert wurden, erfolgt dies nach dem Festlegen der Ansicht.

4. viewWillAppear

Dieses Ereignis benachrichtigt Sie, viewControllerwenn die Ansicht auf dem Bildschirm angezeigt wird. In diesem Schritt hat die Ansicht Grenzen, die definiert sind, aber die Ausrichtung ist nicht festgelegt.

Wird aufgerufen, wenn die Ansicht sichtbar gemacht werden soll. Standard macht nichts.

5. viewWillLayoutSubviews

Dies ist der erste Schritt im Lebenszyklus, in dem die Grenzen festgelegt werden. Wenn Sie keine Einschränkungen oder kein automatisches Layout verwenden, möchten Sie wahrscheinlich die Unteransichten hier aktualisieren. Dies ist nur in iOS> = 5.0 verfügbar. Wenn Sie also iOS <5.0 unterstützen, erwarten Sie nicht, dass es ins Bild kommt.

Wird unmittelbar vor dem Aufruf der layoutSubviews-Methode des View Controllers aufgerufen. Unterklassen können nach Bedarf implementiert werden. Der Standardwert ist nop.

6. viewDidLayoutSubviews

Dieses Ereignis benachrichtigt den Ansichtscontroller, dass die Unteransichten eingerichtet wurden. Es ist ein guter Ort, um Änderungen an den Unteransichten vorzunehmen, nachdem sie festgelegt wurden. Dies ist nur in iOS> = 5.0 verfügbar. Wenn Sie also iOS <5.0 unterstützen, erwarten Sie nicht, dass es ins Bild kommt.

Wird direkt nach dem Aufruf der layoutSubviews-Methode des View Controllers aufgerufen. Unterklassen können nach Bedarf implementiert werden. Der Standardwert ist nop.

7. viewDidAppear

Das viewDidAppearEreignis wird ausgelöst, nachdem die Ansicht auf dem Bildschirm angezeigt wird. Dies macht es zu einem guten Ort, um Daten von einem Backend-Service oder einer Datenbank abzurufen.

Wird aufgerufen, wenn die Ansicht vollständig auf den Bildschirm übertragen wurde. Standard macht nichts

8. viewWillDisappear

Das viewWillDisappearEreignis wird ausgelöst, wenn die Ansicht des Präsentierten viewControllerverschwinden, entlassen, verdeckt oder hinter anderen versteckt werden soll viewController. Dies ist ein guter Ort, an dem Sie Ihre Netzwerkanrufe einschränken, den Timer ungültig machen oder daran gebundene Objekte freigeben können viewController.

Wird aufgerufen, wenn die Ansicht verworfen, verdeckt oder anderweitig ausgeblendet wird.

9. viewDidDisappear

Dies ist der letzte Schritt des Lebenszyklus, den jeder ansprechen kann, wenn dieses Ereignis ausgelöst wird, nachdem die Ansicht der präsentierten viewControllerPerson verschwunden, entlassen, verdeckt oder verborgen wurde.

Wird aufgerufen, nachdem die Ansicht verworfen, verdeckt oder anderweitig ausgeblendet wurde. Standard macht nichts

Laut Apple sollten Sie bei der Implementierung dieser Methoden daran denken, die superImplementierung dieser bestimmten Methode aufzurufen .

Wenn Sie UIViewController unterordnen, müssen Sie die Super-Implementierung dieser Methode aufrufen, auch wenn Sie keine NIB verwenden. (Der Einfachheit halber erledigt die Standard-Init-Methode dies für Sie und gibt für beide Argumente dieser Methode null an.) In der angegebenen NIB sollte für den Proxy des Dateibesitzers die Klasse auf Ihre View Controller-Unterklasse mit dem View-Ausgang festgelegt sein mit der Hauptansicht verbunden. Wenn Sie diese Methode mit einem Null-Nib-Namen aufrufen, -loadViewversucht die Methode dieser Klasse, eine NIB zu laden, deren Name mit der Klasse Ihres View Controllers übereinstimmt. Wenn tatsächlich keine solche NIB vorhanden ist, müssen Sie entweder aufrufen, -setView:bevor sie -viewaufgerufen wird, oder die -loadViewMethode zum programmgesteuerten Einrichten Ihrer Ansichten überschreiben .

Hoffe das hat geholfen. Vielen Dank.

UPDATE - Wie @ThomasW im Kommentar gezeigt hat viewWillLayoutSubviewsund viewDidLayoutSubviewsauch zu anderen Zeiten aufgerufen wird, wenn Unteransichten der Hauptansicht geladen werden, z. B. wenn Zellen einer Tabellenansicht oder einer Sammlungsansicht geladen werden.

UPDATE - Wie @Maria im Kommentar zeigte, wurde die Beschreibung von loadViewaktualisiert

bei Fertigstellung
quelle
6
viewWillLayoutSubviewsund viewDidLayoutSubviewswird auch zu anderen Zeiten aufgerufen, wenn Unteransichten der Hauptansicht geladen werden, z. B. wenn Zellen einer Tabellenansicht oder einer Sammlungsansicht geladen werden.
ThomasW
Diese Antwort ist leicht irreführend: loadView () wird immer aufgerufen und sollte nur nicht überschrieben werden, wenn die Ansicht für den Controller in IB erstellt wird.
Maria
@Maria Bitte bearbeiten Sie die Antwort, wenn Sie der Meinung sind, dass sie verbessert werden kann. Vielen Dank.
onCompletion
Standard macht nichts falsch für viewWillAppear viewDidAppear viewDidDisappear. Sie müssen irgendwann super anrufen.
Mick
47

iOS 10,11 (Swift 3.1, Swift 4.0)

Laut UIViewControllerin UIKitEntwicklern,

1. loadView ()

Hier sollten Unterklassen ihre benutzerdefinierte Ansichtshierarchie erstellen, wenn sie keine Schreibfeder verwenden . Sollte niemals direkt angerufen werden.

2. loadViewIfNeeded ()

Lädt die Ansicht des View Controllers, falls diese noch nicht festgelegt wurde.

3. viewDidLoad ()

Wird aufgerufen, nachdem die Ansicht geladen wurde. Für im Code erstellte Ansichtscontroller ist dies nach -loadView. Bei Ansichtscontrollern, die nicht von einer Schreibfeder archiviert wurden, erfolgt dies nach dem Festlegen der Ansicht.

4. viewWillAppear (_ animiert: Bool)

Wird aufgerufen, wenn die Ansicht sichtbar gemacht werden soll. Standard macht nichts

5. viewWillLayoutSubviews ()

Wird unmittelbar vor dem Aufruf der layoutSubviews-Methode des View Controllers aufgerufen. Unterklassen können nach Bedarf implementiert werden. Standard macht nichts.

6. viewDidLayoutSubviews ()

Wird direkt nach dem Aufruf der layoutSubviews-Methode des View Controllers aufgerufen. Unterklassen können nach Bedarf implementiert werden. Standard macht nichts.

7. viewDidAppear (_ animiert: Bool)

Wird aufgerufen, wenn die Ansicht vollständig auf den Bildschirm übertragen wurde. Standard macht nichts

8. viewWillDisappear (_ animiert: Bool)

Wird aufgerufen, wenn die Ansicht verworfen, verdeckt oder anderweitig ausgeblendet wird. Standard macht nichts

9. viewDidDisappear (_ animiert: Bool )

Wird aufgerufen, nachdem die Ansicht entlassen, verdeckt oder anderweitig ausgeblendet wurde. Standard macht nichts

10. viewWillTransition (auf Größe: CGSize, mit Koordinator: UIViewControllerTransitionCoordinator)

Wird aufgerufen, wenn die Ansicht "Übergang" ist.

11. willMove (toParentViewController Eltern: UIViewController?)

12. didMove (toParentViewController Eltern: UIViewController?)

Diese beiden Methoden sind öffentlich, damit Container-Unterklassen beim Übergang zwischen untergeordneten Controllern aufgerufen werden können. Wenn sie überschrieben werden, sollten die Überschreibungen sicherstellen, dass der Super aufgerufen wird.

Das übergeordnete Argument in beiden Methoden ist null, wenn ein untergeordnetes Element aus seinem übergeordneten Element entfernt wird. Andernfalls entspricht es dem neuen übergeordneten Ansichtscontroller.

13. didReceiveMemoryWarning ()

Wird aufgerufen, wenn die übergeordnete Anwendung eine Speicherwarnung erhält. Unter iOS 6.0 wird die Ansicht standardmäßig nicht mehr gelöscht.

Rajamohan S.
quelle
2
Es ist wirklich sehr wichtig, dass der Stackoverflow nicht alle falschen und unvollständigen Antworten aus diesem gesamten Thread entfernt. Ihre Antwort scheint in Bezug auf Methodenaufrufe vollständig zu sein, daher gehe ich davon aus, dass Ihre richtig ist, und arbeite damit.
Logicsaurus Rex
Was ist ein nibwie unter erwähnt loadView?
Petrus Theron
2
@LogicsaurusRex Ich stimme zu. Genauso wie SO Fragen als Duplikate oder geschützt markiert, sollte es meiner Meinung nach in der Lage sein, Antworten als veraltet oder veraltet
rmp251
Punkt 5 oben ist falsch. viewWillLayoutSubviews()wird aufgerufen, bevor das View-Objekt des ViewControllers seine layoutSubviews()Methode aufruft
williamukoh
28

Ab iOS 6 und höher. Das neue Diagramm sieht wie folgt aus:

Geben Sie hier die Bildbeschreibung ein

Saad
quelle
1
Nennen Sie diese Ansicht "A". Stellen Sie sich eine zweite Ansicht "B" vor, die angezeigt wird, während "A" verschwindet. Ist "B.viewWillAppear" vor oder nach "A.viewDidDisappear"? Und gibt es Situationen, in denen sich die Reihenfolge dieser beiden ändert?
ToolmakerSteve
Scheint, als würde der Wille einer neuen Ansicht (B) vor dem Verschwinden aufgerufen. Zur zweiten Frage. Brauchen Sie etwas Zeit, um es zu untersuchen.
Saad
21

Konzentrieren wir uns auf Methoden, die für den Lebenszyklus des UIViewControllers verantwortlich sind :

  • Schaffung:

    - (void)init

    - (void)initWithNibName:

  • Ansicht erstellen:

    - (BOOL)isViewLoaded

    - (void)loadView

    - (void)viewDidLoad

    - (UIView *)initWithFrame:(CGRect)frame

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

  • Behandlung der Änderung des Ansichtsstatus:

    - (void)viewDidLoad

    - (void)viewWillAppear:(BOOL)animated

    - (void)viewDidAppear:(BOOL)animated

    - (void)viewWillDisappear:(BOOL)animated

    - (void)viewDidDisappear:(BOOL)animated

    - (void)viewDidUnload

  • Behandlung von Speicherwarnungen:

    - (void)didReceiveMemoryWarning

  • Freigabe

    - (void)viewDidUnload

    - (void)dealloc

Lebenszyklusdiagramm von UIViewController

Weitere Informationen finden Sie in der UIViewController-Klassenreferenz .

Alexey Pelekh
quelle
19

Die Methoden viewWillLayoutSubviewsund viewDidLayoutSubviewswerden in den Diagrammen nicht erwähnt, aber diese werden zwischen viewWillAppearund aufgerufen viewDidAppear. Sie können mehrfach aufgerufen werden.

gjgjgj
quelle
Sie werden auch zu anderen Zeiten aufgerufen, wenn Unteransichten der Hauptansicht geladen werden, z. B. wenn Zellen einer Tabellenansicht oder einer Sammlungsansicht geladen werden.
ThomasW
16

Die Antwort von Haider ist für iOS 6 korrekt. Ab iOS 6 werden viewDidUnload und viewWillUnload jedoch nie mehr aufgerufen. In den Dokumenten heißt es : "Ansichten werden unter Bedingungen mit wenig Arbeitsspeicher nicht mehr gelöscht, daher wird diese Methode niemals aufgerufen."

Matt Becker
quelle
Ich habe versucht, einen Haltepunkt in ViewWillDisappear, ViewDidDisappear, Dispose einzufügen. Aber keiner von ihnen wurde aufgerufen, als ich mit der PresentViewController () -Methode navigierte. Was könnte der Grund sein?
Sreeraj
1
Der Link funktioniert nicht ... Was macht das Betriebssystem bei wenig Arbeitsspeicher?
Sohn
Speichert sie auf der Festplatte?
Ian Warburton
16

Hier gibt es viele veraltete und unvollständige Informationen. Nur für iOS 6 und neuer :

  1. loadView[ein]
  2. viewDidLoad[ein]
  3. viewWillAppear
  4. viewWillLayoutSubviews ist das erste Mal, dass Grenzen festgelegt werden
  5. viewDidLayoutSubviews
  6. viewDidAppear
  7. * viewWillLayoutSubviews[b]
  8. * viewDidLayoutSubviews[b]

Fußnoten:

(a) - Wenn Sie manuell nil aus Ihrer Sicht bei didReceiveMemoryWarning, loadViewund viewDidLoadwieder aufgerufen werden. Das heißt, standardmäßig loadViewund wird viewDidLoadnur einmal pro View Controller-Instanz aufgerufen.

(b) Kann zusätzlich 0 oder mehrmals aufgerufen werden .

Bobics
quelle
1
viewWillLayoutSubviewsund viewDidLayoutSubviewswird auch zu anderen Zeiten aufgerufen, wenn Unteransichten der Hauptansicht geladen werden, z. B. wenn Zellen einer Tabellenansicht oder einer Sammlungsansicht geladen werden.
ThomasW
11

Erläutern von Zustandsübergängen im offiziellen Dokument: https://developer.apple.com/library/ios/documentation/uikit/reference/UIViewController_Class/index.html

Dieses Bild zeigt die gültigen Zustandsübergänge zwischen verschiedenen Rückrufmethoden für "Will" und "Did"

Gültige Zustandsübergänge:


Entnommen aus: https://developer.apple.com/library/ios/documentation/uikit/reference/UIViewController_Class/Art/UIViewController Class Reference_2x.png

Luismi
quelle
0

Gemäß Apples Dokument - Entwickeln von iOS-Apps (Swift) beginnen - Mit View Controllern arbeiten - Den View Controller-Lebenszyklus verstehen

viewDidLoad()- Wird aufgerufen, wenn die Inhaltsansicht des Ansichtscontrollers (oben in der Ansichtshierarchie) erstellt und aus einem Storyboard geladen wird. … Verwenden Sie diese Methode, um zusätzliche Einstellungen vorzunehmen, die von Ihrem View Controller benötigt werden.

viewWillAppear()- Wird unmittelbar vor dem Hinzufügen der Inhaltsansicht des Ansichtscontrollers zur Ansichtshierarchie der App aufgerufen. Verwenden Sie diese Methode, um alle Vorgänge auszulösen, die ausgeführt werden müssen, bevor die Inhaltsansicht auf dem Bildschirm angezeigt wird

viewDidAppear()- Wird unmittelbar nach dem Hinzufügen der Inhaltsansicht des Ansichtscontrollers zur Ansichtshierarchie der App aufgerufen. Verwenden Sie diese Methode, um alle Vorgänge auszulösen, die ausgeführt werden müssen, sobald die Ansicht auf dem Bildschirm angezeigt wird, z. B. das Abrufen von Daten oder das Anzeigen einer Animation.

viewWillDisappear()- Wird unmittelbar vor dem Entfernen der Inhaltsansicht des Ansichtscontrollers aus der Ansichtshierarchie der App aufgerufen. Verwenden Sie diese Methode, um Bereinigungsaufgaben wie das Festschreiben von Änderungen oder das Zurücktreten des Ersthelferstatus auszuführen.

viewDidDisappear()- Wird unmittelbar nach dem Entfernen der Inhaltsansicht des Ansichtscontrollers aus der Ansichtshierarchie der App aufgerufen. Verwenden Sie diese Methode, um zusätzliche Abreißaktivitäten durchzuführen.

Fred
quelle