Der ViewController Lifecycle ist die Sequenz von Methoden, die UIKit beim Verwalten von Bildschirmen in iOS automatisch aufruft. Laut Apple Dokumentation durchläuft jeder UIViewController einen vorhersagbaren Satz von Zuständen: von der Erstellung der View bis zu ihrem Erscheinen und Verschwinden. Das Verstehen der Reihenfolge und des Zwecks dieser Methoden ist eine notwendige Bedingung für den stabilen Betrieb einer iOS-App.
Wichtige Punkte
ViewController Lifecycle ist eine Reihe von Methoden, die UIViewController während seiner Existenz von UIKit erhält. Jeder Bildschirm in einer iOS-App durchläuft nacheinander die Phasen der Erstellung, des Ladens der View, des Erscheinens auf dem Bildschirm, des Verschwindens und der Speicherfreigabe. UIKit ruft in jeder Phase automatisch die entsprechenden Methoden auf, und der Entwickler überschreibt sie, um seine eigene Logik hinzuzufügen.
Die UIViewController-Architektur ist die Grundlage von UIKit und bleibt auch im SwiftUI-Zeitalter relevant — viele Projekte verwenden immer noch den klassischen Ansatz oder eine hybride Architektur. Das Verständnis des Lifecycle ermöglicht es, vorherzusagen, wann Subviews verfügbar sind, wann es sicher ist, das Layout zu ändern und welche Operationen beim Erscheinen oder Verschwinden des Bildschirms durchgeführt werden sollen.
Jede Lebenszyklus-Methode hat einen spezifischen Zweck: einige werden während der gesamten Lebensdauer des Controllers nur einmal aufgerufen, andere — bei jedem Erscheinen oder Verschwinden. Das Vermischen der Logik zwischen den Methoden führt zu schwer auffindbaren Fehlern: Speicherlecks, falsche Datenaktualisierungen und unnötige Netzwerkanfragen.
Sechs Methoden bilden den vollständigen Lebenszyklus von UIViewController. Die Aufrufreihenfolge ist festgelegt und hängt nicht von der Navigationsmethode ab — push, present oder unwind segue folgen alle demselben Zeitplan.
loadView ist die erste Methode des Zyklus, die aufgerufen wird, wenn die View des Controllers noch nicht existiert. Wenn Sie Storyboard verwenden, lädt UIKit automatisch die View aus der xib-Datei. Bei der programmatischen Erstellung der Benutzeroberfläche überschreiben Sie diese Methode, indem Sie die Root-View manuell zuweisen. In den meisten Projekten wird loadView nicht angerührt — die Arbeit wird in viewDidLoad erledigt.
Das Überschreiben von loadView ist nur in spezifischen Fällen erforderlich: wenn die gesamte Benutzeroberfläche ohne Storyboard im Code erstellt wird, oder wenn die Root-View von einer nicht standardmäßigen Klasse sein muss. Apple empfiehlt, beim Überschreiben super.loadView nicht aufzurufen — Sie übernehmen die volle Verantwortung für die Erstellung der View.
override func loadView() {
view = UIView()
view.backgroundColor = .white
}
viewDidLoad ist die am häufigsten verwendete Methode des Zyklus. Sie wird einmal aufgerufen, nachdem die View in den Speicher geladen wurde, aber noch nicht auf dem Bildschirm angezeigt wird. Hier werden Subviews konfiguriert, Tabellen mit Daten befüllt, Zellen registriert und Benachrichtigungen abonniert, die während der gesamten Lebensdauer des Controllers bestehen bleiben.
Eine wichtige Eigenschaft: viewDidLoad wird bei erneuter Anzeige des Bildschirms nicht erneut aufgerufen. Wenn Sie Daten jedes Mal aktualisieren müssen, wenn der Bildschirm erscheint — verwenden Sie viewWillAppear. Platzieren Sie in viewDidLoad nur einmalige Operationen, die für die grundlegende Konfiguration erforderlich sind.
viewWillAppear wird jedes Mal unmittelbar bevor die View für den Benutzer sichtbar wird, aufgerufen. Diese Methode erhält einen animated-Parameter, der angibt, ob das Erscheinen animiert ist. Hier werden Daten aktualisiert, Tabellen neu geladen, die NavigationBar konfiguriert und Elemente je nach Anwendungszustand ein- oder ausgeblendet.
Verwenden Sie viewWillAppear zur Zustandssynchronisation zwischen Bildschirmen: wenn der Benutzer auf dem vorherigen Bildschirm Daten geändert haben könnte, ist diese Methode der richtige Ort, um die Benutzeroberfläche zu aktualisieren. Jeder Aufruf von viewWillAppear geht dem Erscheinen des Bildschirms voraus, auch bei der Rückkehr von einem untergeordneten Controller.
viewDidAppear benachrichtigt, dass die View vollständig auf dem Bildschirm erschienen ist und alle Übergangsanimationen abgeschlossen sind. Zu diesem Zeitpunkt ist der Bildschirm bereit für die Interaktion — der Benutzer sieht die vollständige Oberfläche und kann mit ihr interagieren. Diese Methode eignet sich zum Starten von Animationen, die nach dem Erscheinen beginnen sollen, zum Starten von Timern und zum Verfolgen von Analyse-Impressions.
Im Gegensatz zu viewWillAppear garantiert viewDidAppear, dass der Bildschirm nicht nur sichtbar, sondern auch vollständig gerendert ist. Wenn Sie eine Animation in viewWillAppear starten, können einige Frames übersprungen werden, da UIKit den Übergang noch nicht abgeschlossen hat. Für flüssige Animationen verwenden Sie viewDidAppear.
viewWillDisappear wird vor dem Verschwinden der View vom Bildschirm aufgerufen — beim Übergang zu einem anderen Controller, beim Schließen eines modalen Fensters oder beim Suspendieren der App. Dies ist der richtige Ort, um den Zustand zu speichern, Benachrichtigungen zu abzubestellen, aktive Prozesse zu stoppen und Ressourcen freizugeben, die nicht benötigt werden, wenn der Bildschirm nicht sichtbar ist.
Wichtig zu beachten: viewWillDisappear garantiert nicht, dass die View letztendlich verschwindet — die Geste kann abgebrochen werden. Speichern Sie kritische Daten daher auch in viewDidDisappear, das erst nach dem tatsächlichen Verschwinden aufgerufen wird.
viewDidDisappear schließt den Erscheinungs- und Verschwindenszyklus ab. Es wird aufgerufen, nachdem die View bereits vom Bildschirm ausgeblendet ist. In dieser Methode werden Animationen endgültig gestoppt, temporäre Objekte entfernt und das in viewWillDisappear begonnene Speichern von Daten bestätigt.
Diese Methode geht auch dem deinit des Controllers voraus — wenn Ihr UIViewController zerstört wird, ist viewDidDisappear die letzte Lifecycle-Methode vor dem Aufruf von deinit. Verwenden Sie sie für die endgültige Bereinigung, die vor der Zerstörung des Objekts erfolgen soll.
Die Reihenfolge der Aufrufe hängt davon ab, wie der Bildschirm erscheint: zum ersten Mal, beim Zurückgehen oder bei modaler Präsentation. Betrachten wir drei Hauptszenarien aus der Perspektive von UIKit.
Wenn ein Bildschirm zum ersten Mal erscheint, durchläuft UIKit den vollständigen Erstellungszyklus: loadView wird aufgerufen, dann viewDidLoad, danach beginnt die Erscheinungsanimation. Während der Animation wird viewWillAppear aufgerufen, und nach Abschluss — viewDidAppear. Dies ist das einzige Szenario, bei dem alle Methoden von loadView bis viewDidAppear nacheinander ausgelöst werden.
override func viewDidLoad() {
super.viewDidLoad()
print("viewDidLoad — View in Speicher geladen")
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
print("viewWillAppear — Wird gleich erscheinen")
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
print("viewDidAppear — Bildschirm vollständig sichtbar")
}
Wenn der Benutzer zu einem vorherigen Bildschirm zurückgeht, ruft UIKit viewDidLoad nicht erneut auf — die View ist bereits im Speicher geladen. Stattdessen werden nur viewWillAppear und viewDidAppear auf dem zurückkehrenden Bildschirm aufgerufen, und auf dem aktuellen — viewWillDisappear und viewDidDisappear. loadView und viewDidLoad werden übersprungen, da der Bildschirm bereits im Navigationsstapel existiert.
Die modale Präsentation folgt denselben Regeln: der neue Controller durchläuft den vollständigen Zyklus beim ersten Erscheinen, während der aktuelle viewWillDisappear und viewDidDisappear erhält. Beim Dismiss wird die Reihenfolge umgekehrt: der zurückkehrende Controller erhält erneut viewWillAppear und viewDidAppear, während der verworfene die abschließenden Methoden erhält. Dieses Verhalten ist für alle Übergangstypen in UIKit einheitlich.
Betrachten wir vier Schlüsselszenarien, bei denen das Verständnis des Lifecycle die Codequalität und das Benutzererlebnis direkt beeinflusst. Für jedes Szenario geben wir ein Beispiel mit Empfehlungen.
viewDidLoad ist der Ort für die anfängliche Einrichtung, die nicht von der Sichtbarkeit des Bildschirms abhängt. Hier wird das collectionView konfiguriert, nib-Dateien für Zellen registriert, Datenquellen und Layouts erstellt. Wenn Sie Daten aus dem Netzwerk laden, ist es in viewDidLoad besser, nur die Anfrage zu initiieren und die UI in viewWillAppear zu aktualisieren, wenn der Bildschirm zur Anzeige bereit ist.
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(
MyCell.self,
forCellReuseIdentifier: MyCell.identifier
)
viewModel.loadInitialData()
}
Verwenden Sie viewWillAppear zur Datensynchronisation jedes Mal, wenn der Bildschirm erscheint. Wenn der Benutzer beispielsweise auf dem vorherigen Bildschirm Einstellungen geändert haben könnte, werden hier die angezeigten Werte aktualisiert, die Tabelle neu geladen und der Status der NavigationBar angepasst. Dies garantiert, dass der Bildschirm in jedem Navigationsszenario immer aktuelle Daten anzeigt.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
tableView.reloadData()
navigationController?.setNavigationBarHidden(false, animated: animated)
}
viewDidAppear ist ideal zum Starten von Animationen, die beginnen sollen, nachdem der Benutzer den Bildschirm gesehen hat. Hier senden Sie auch Analyseereignisse: Bildschirmaufruf, Onboarding-Start oder Videowiedergabe. Das Starten von Animationen vor Abschluss des Übergangs führt zu einer ruckelnden Oberfläche — UIKit hat nicht genügend Zeit, um eine ausreichende Anzahl von Frames vorzubereiten.
In viewWillDisappear speichern Sie Entwürfe, stoppen Timer und melden Benachrichtigungen von NotificationCenter ab. Dies ist der letzte Moment, in dem der Bildschirm noch sichtbar und für Operationen zugänglich ist, die Benutzerkontext erfordern. Für kritische Daten verwenden Sie zusätzlich viewDidDisappear als Schutz vor abgebrochenen Gesten.
Die falsche Verwendung von Lebenszyklus-Methoden ist eine der häufigsten Fehlerquellen in iOS-Apps. Betrachten wir die wichtigsten Fehler, die Entwickler in verschiedenen Phasen der Arbeit mit UIViewController machen.
Der erste Fehler — das Erstellen von Subviews in init oder loadView bei Verwendung von Storyboard. Wenn Sie Interface Builder verwenden, überschreiben Sie loadView nicht unnötig. Das Erstellen einer View in loadView, wenn ein Storyboard vorhanden ist, führt dazu, dass die xib-Datei ignoriert wird und ein leerer Bildschirm erscheint.
Der zweite Fehler — das Abonnieren von Tastaturbenachrichtigungen in viewDidLoad ohne Abbestellung. Wenn Sie UIResponder.keyboardWillShowNotification abonniert, aber beim Ausblenden des Bildschirms nicht abbestellt haben, wird der Block auch nach dem deinit des Controllers weiter aufgerufen — dies ist ein Speicherleck mit möglichem Absturz der App.
Der dritte Fehler — Timer und Netzwerkanfragen, die gestartet werden, bevor der Bildschirm erscheint. Das Laden von Bildern oder das Ausführen von Animationen, wenn die View noch nicht sichtbar ist, ist eine Verschwendung von Ressourcen. Verschieben Sie visuelle Aktualisierungen in viewWillAppear oder viewDidAppear.
Der vierte Fehler — das Speichern von Daten nur in viewWillDisappear. Bei einer interaktiven Pop-Geste kann der Benutzer einen Wischvorgang beginnen und abbrechen — die Methode wurde aufgerufen, aber der Bildschirm ist nicht verschwunden. Duplizieren Sie das kritische Speichern in viewDidDisappear oder im applicationDidEnterBackground-Handler.
Häufig gestellte Fragen
Einmal — nach dem Laden der View in den Speicher. Wenn der Bildschirm erneut erscheint, wird viewDidLoad nicht aufgerufen. Wenn Sie die View neu erstellen müssen, muss der Controller zerstört und neu erstellt werden.
UIKit erfordert den Aufruf von super.viewDidLoad, damit der Lebenszyklus korrekt funktioniert. Ohne ihn können Probleme bei Layout-Aktualisierungen und der Verarbeitung von Übergängen auftreten. Rufen Sie super immer als Erstes innerhalb der Methode auf.
Nicht empfohlen. Wenn der Controller aus Storyboard initialisiert wird, lädt UIKit automatisch die View aus der xib. Das Überschreiben von loadView bricht diesen Prozess ab und Ihr Storyboard wird ignoriert.
Abonnieren Sie in viewDidLoad oder viewWillAppear und melden Sie in viewWillDisappear oder viewDidDisappear ab, wobei Sie eine schwache Referenz auf self verwenden, um Speicherlecks bei Closures zu vermeiden.
Force quit beendet den Prozess abrupt — UIKit hat keine Zeit, Lifecycle-Methoden aufzurufen. Verwenden Sie zum Speichern von Daten die Benachrichtigung UIApplication.willTerminateNotification im AppDelegate.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch