ViewController Lifecycle — is een reeks methoden die UIKit automatisch aanroept bij het beheren van schermen in iOS. Volgens Apple Documentation doorloopt elke UIViewController een voorspelbare reeks toestanden: van het maken van de View tot het verschijnen en verbergen ervan. Het begrijpen van de volgorde en het doel van deze methoden is een noodzakelijke voorwaarde voor stabiele werking van een iOS-app.
Belangrijkste
ViewController Lifecycle — is een set methoden die UIViewController van UIKit ontvangt gedurende zijn bestaan. Elk scherm in een iOS-app doorloopt achtereenvolgens de stadia van aanmaken, laden van de View, verschijnen op het scherm, verdwijnen en vrijgeven van geheugen. UIKit roept automatisch de juiste methoden aan in elk stadium en de ontwikkelaar overschrijft ze om eigen logica toe te voegen.
De architectuur van UIViewController vormt de basis van UIKit en blijft relevant, zelfs in het tijdperk van SwiftUI — veel projecten gebruiken nog steeds de klassieke benadering of hybride architectuur. Inzicht in de Lifecycle maakt het mogelijk te voorspellen wanneer subviews beschikbaar zijn, wanneer de lay-out veilig kan worden gewijzigd en welke bewerkingen moeten worden uitgevoerd bij het verschijnen of verbergen van het scherm.
Elke methode van de levenscyclus heeft een specifiek doel: sommige worden eenmaal aangeroepen gedurende het bestaan van de controller, andere — bij elke verschijning of verdwijning. Het mengen van logica tussen methoden leidt tot moeilijk vindbare bugs: geheugenlekken, onjuiste gegevensupdates en onnodige netwerkverzoeken.
Zes methoden vormen de volledige levenscyclus van UIViewController. De volgorde van aanroepen is vast en hangt niet af van de navigatiemethode — push, present of unwind segue volgen hetzelfde schema.
loadView — de eerste methode van de cyclus, aangeroepen wanneer de View van de controller nog niet bestaat. Als je Storyboard gebruikt, laadt UIKit automatisch de View uit het xib-bestand. Bij het programmatisch creëren van de interface overschrijf je deze methode en wijs je handmatig de root-View toe. In de meeste projecten wordt loadView niet aangeraakt — het werk gebeurt in viewDidLoad.
Het overschrijven van loadView is alleen nodig in specifieke gevallen: wanneer de hele interface met code wordt gemaakt zonder Storyboard of wanneer de root-View van een niet-standaard klasse moet zijn. Apple raadt aan om super.loadView niet aan te roepen bij het overschrijven — je neemt het maken van de View volledig over.
override func loadView() {
view = UIView()
view.backgroundColor = .white
}
viewDidLoad — de meest gebruikte methode van de cyclus. Het wordt eenmaal aangeroepen nadat de View in het geheugen is geladen, maar nog niet op het scherm wordt weergegeven. Hier worden subviews geconfigureerd, tabellen met gegevens gevuld, cellen geregistreerd en meldingen geabonneerd die gedurende de hele levensduur van de controller actief zijn.
Belangrijk kenmerk: viewDidLoad wordt niet opnieuw aangeroepen bij het opnieuw weergeven van het scherm. Als je elke keer bij verschijning gegevens moet bijwerken — gebruik dan viewWillAppear. Plaats in viewDidLoad alleen eenmalige bewerkingen waarvan de basisconfiguratie afhankelijk is.
viewWillAppear wordt elke keer direct voordat de View zichtbaar wordt voor de gebruiker aangeroepen. Deze methode ontvangt de parameter animated, die aangeeft of de verschijning met animatie plaatsvindt. Hier worden gegevens bijgewerkt, tabellen herladen, NavigationBar geconfigureerd en elementen verborgen of getoond afhankelijk van de status van de app.
Gebruik viewWillAppear voor het synchroniseren van de status tussen schermen: als de gebruiker gegevens op het vorige scherm heeft kunnen wijzigen, is deze methode de juiste plek om de interface bij te werken. Elke aanroep van viewWillAppear gaat vooraf aan het verschijnen van het scherm, zelfs bij terugkeer van een child-controller.
viewDidAppear geeft aan dat de View volledig op het scherm is verschenen en alle overgangsanimaties zijn voltooid. Op dit moment is het scherm klaar voor interactie — de gebruiker ziet de volledige interface en kan ermee werken. Deze methode is geschikt voor het starten van animaties die na verschijning moeten beginnen, het starten van timers en het volgen van analyseweergaven.
In tegenstelling tot viewWillAppear garandeert viewDidAppear dat het scherm niet alleen zichtbaar is, maar volledig gerenderd. Als je een animatie start in viewWillAppear, kunnen sommige frames worden overgeslagen omdat UIKit de overgang nog niet heeft voltooid. Gebruik viewDidAppear voor vloeiende animaties.
viewWillDisappear wordt aangeroepen voordat de View van het scherm verdwijnt — bij overgang naar een andere controller, sluiten van een modaal venster of minimaliseren van de app. Dit is de juiste plek om de status op te slaan, meldingen te deabonneren, actieve processen te stoppen en bronnen vrij te geven die niet nodig zijn wanneer het scherm niet zichtbaar is.
Belangrijk om te onthouden: viewWillDisappear garandeert niet dat de View uiteindelijk verdwijnt — het gebaar kan worden geannuleerd. Sla daarom kritieke gegevens ook op in viewDidDisappear, dat pas wordt aangeroepen na daadwerkelijke verdwijning.
viewDidDisappear voltooit de cyclus van verschijnen en verdwijnen. Het wordt aangeroepen nadat de View al van het scherm is verborgen. In deze methode worden animaties definitief gestopt, tijdelijke objecten verwijderd en de opslag van gegevens die in viewWillDisappear is gestart, bevestigd.
Deze methode gaat ook vooraf aan deinit van de controller — als je UIViewController wordt vernietigd, is viewDidDisappear de laatste Lifecycle-methode vóór de aanroep van deinit. Gebruik het voor definitieve opschoning die moet plaatsvinden vóór vernietiging van het object.
De volgorde van aanroepen hangt af van hoe het scherm precies verschijnt: voor het eerst, bij terugkeer of bij modale weergave. Laten we drie hoofscenario’s bekijken vanuit het perspectief van UIKit.
Bij de eerste verschijning van het scherm doorloopt UIKit de volledige creatiecyclus: loadView wordt aangeroepen, vervolgens viewDidLoad, waarna de verschijningsanimatie start. Tijdens de animatie wordt viewWillAppear aangeroepen en na voltooiing — viewDidAppear. Dit is het enige scenario waarin alle methoden van loadView tot viewDidAppear achtereenvolgens worden aangeroepen.
override func viewDidLoad() {
super.viewDidLoad()
print("viewDidLoad — View geladen in geheugen")
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
print("viewWillAppear — verschijnt binnenkort")
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
print("viewDidAppear — scherm volledig zichtbaar")
}
Wanneer de gebruiker terugkeert naar het vorige scherm, roept UIKit viewDidLoad niet opnieuw aan — de View is al in het geheugen geladen. In plaats daarvan worden op het terugkerende scherm alleen viewWillAppear en viewDidAppear geactiveerd en op het huidige scherm — viewWillDisappear en viewDidDisappear. loadView en viewDidLoad worden overgeslagen omdat het scherm al in de navigatiestapel bestaat.
Modale weergave volgt dezelfde regels: bij de nieuwe controller wordt de volledige cyclus aangeroepen bij eerste verschijning en bij de huidige — viewWillDisappear en viewDidDisappear. Bij dismiss is de volgorde omgekeerd: bij de terugkerende controller worden opnieuw viewWillAppear en viewDidAppear geactiveerd en bij de verborgen controller — de afsluitende methoden. Dit gedrag is uniform voor alle overgangstypen in UIKit.
Laten we vier belangrijke scenario’s bekijken waarin inzicht in de Lifecycle direct van invloed is op de kwaliteit van code en gebruikerservaring. Voor elk scenario geven we een voorbeeld met aanbevelingen.
viewDidLoad — de plek voor initiële configuratie die onafhankelijk is van de zichtbaarheid van het scherm. Hier worden collectionView geconfigureerd, nib-bestanden voor cellen geregistreerd, data source en lay-out gemaakt. Als je gegevens uit het netwerk laadt, kun je in viewDidLoad beter alleen het verzoek starten en de interface bijwerken in viewWillAppear, wanneer het scherm klaar is voor weergave.
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(
MyCell.self,
forCellReuseIdentifier: MyCell.identifier
)
viewModel.loadInitialData()
}
Gebruik viewWillAppear om gegevens elke keer bij verschijning van het scherm te synchroniseren. Als de gebruiker bijvoorbeeld instellingen op het vorige scherm heeft kunnen wijzigen, worden hier de weergegeven waarden bijgewerkt, de tabel herladen en de status van NavigationBar gecorrigeerd. Dit garandeert dat het scherm altijd actuele gegevens toont bij elk navigatiescenario.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
tableView.reloadData()
navigationController?.setNavigationBarHidden(false, animated: animated)
}
viewDidAppear is ideaal voor het starten van animaties die moeten beginnen nadat de gebruiker het scherm heeft gezien. Hier worden ook analytics-gebeurtenissen verzonden: schermweergave, start van onboarding of begin van video-afspelen. Het starten van animaties vóór voltooiing van de overgang leidt tot een schokkerige interface — UIKit heeft niet genoeg tijd om voldoende frames voor te bereiden.
In viewWillDisappear worden concepten opgeslagen, timers gestopt en deabonnementen van NotificationCenter uitgevoerd. Dit is het laatste moment waarop het scherm nog zichtbaar en beschikbaar is voor bewerkingen die gebruikerscontext vereisen. Voor kritieke gegevens wordt aanvullend viewDidDisappear gebruikt als verzekering tegen geannuleerde gebaren.
Onjuist gebruik van levenscyclusmethoden is een van de meest voorkomende bronnen van bugs in iOS-apps. Laten we de belangrijkste fouten bekijken die ontwikkelaars maken in verschillende fasen van het werken met UIViewController.
Eerste fout — het aanmaken van subviews in init of loadView bij gebruik van Storyboard. Als je Interface Builder gebruikt, overschrijf loadView dan niet onnodig. Het aanmaken van de View in loadView met een bestaand storyboard leidt tot het negeren van het xib-bestand en een leeg scherm.
Tweede fout — abonneren op toetsenbordmeldingen in viewDidLoad zonder deabonneren. Als je je hebt geabonneerd op UIResponder.keyboardWillShowNotification maar niet hebt gedeabonneerd bij het verbergen van het scherm, wordt het blok ook na deinit van de controller aangeroepen — dit is een geheugenlek met mogelijke crash van de app.
Derde fout — timers en netwerkverzoeken die zijn gestart voordat het scherm verscheen. Het laden van afbeeldingen of het uitvoeren van animaties terwijl de View nog niet zichtbaar is — verspilling van bronnen. Verplaats visuele updates naar viewWillAppear of viewDidAppear.
Vierde fout — gegevens alleen opslaan in viewWillDisappear. Bij het interactieve pop-gebaar kan de gebruiker een veegbeweging starten en annuleren — de methode is aangeroepen, maar het scherm is niet verdwenen. Dupliceer kritieke opslag in viewDidDisappear of in de handler van applicationDidEnterBackground.
Veelgestelde vragen
Één keer — nadat de View in het geheugen is geladen. Bij herhaalde verschijningen van het scherm wordt viewDidLoad niet aangeroepen. Als de View opnieuw moet worden aangemaakt, moet de controller worden vernietigd en opnieuw worden gecreëerd.
UIKit vereist het aanroepen van super.viewDidLoad voor een correcte werking van de levenscyclus. Zonder dit kunnen problemen optreden met lay-outupdates en verwerking van overgangen. Roep super altijd als eerste aan in de methode.
Wordt niet aanbevolen. Als de controller is geïnitialiseerd vanuit Storyboard, laadt UIKit automatisch de View uit xib. Het overschrijven van loadView annuleert dit proces en je storyboard wordt genegeerd.
Abonneer in viewDidLoad of viewWillAppear en deabonneer in viewWillDisappear of viewDidDisappear, met een zwakke verwijzing naar self om geheugenlekken bij closures te voorkomen.
Force quit beëindigt het proces geforceerd — UIKit heeft geen tijd om Lifecycle-methoden aan te roepen. Gebruik voor het opslaan van gegevens de melding UIApplication.willTerminateNotification in AppDelegate.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook