ViewController Lifecycle — a metódusok sorozata, amelyeket az UIKit automatikusan meghív a képernyők kezelésekor iOS-ben. Az Apple Documentation szerint minden UIViewController egy kiszámítható állapotsorozaton megy keresztül: a View létrehozásától annak megjelenéséig és elrejtésig. E metódusok sorrendjének és céljának megértése elengedhetetlen feltétele az iOS-alkalmazás stabil működésének.
Főbb pontok
ViewController Lifecycle — metódusok halmaza, amelyeket a UIViewController az UIKit-től kap a fennállása során. Minden képernyő egy iOS-alkalmazásban egymást követve megy keresztül a létrehozás, a View betöltése, a képernyőn való megjelenés, az eltűnés és a memóriafelszabadítás szakaszain. Az UIKit automatikusan meghívja a megfelelő metódusokat minden szakaszban, a fejlesztő pedig felülírja ezeket, hozzáadva saját logikáját.
A UIViewController architektúra az UIKit alapját képezi és a SwiftUI korszakában is releváns marad — sok projekt továbbra is a klasszikus megközelítést vagy hibrid architektúrát használja. A Lifecycle megértése lehetővé teszi annak elŐrejelzését, hogy mikor érhetőek el a subviews, mikor lehet biztonságosan módosítani a layout-ot, és milyen műveleteket kell végezni a képernyő megjelenése vagy elrejtésekor.
Az életciklus metódusainak mindegyikének konkrét célja van: néhány egyszer hívódik meg a vezérlő teljes fennállása során, mások — minden megjelenéskor vagy eltűnéskor. A logika metódusok közötti keverése nehezen észlelhető hibákhoz vezet: memóriaszivárgáshoz, helytelen adatfrissítéshez és felesleges hálózati kérésekhez.
Hat metódus alkotja a UIViewController teljes életciklusát. Meghívásuk sorrendje rögzített és nem függ a navigáció módjától — a push, present és unwind segue ugyanazt az ütemezést követi.
loadView — a ciklus első metódusa, akkor hívódik, amikor a vezérlő View-ja még nem létezik. Ha Storyboard-ot használ, az UIKit automatikusan betölti a View-t az xib-fájlból. Programozott felületlétrehozáskor felülírja ezt a metódust, és manuálisan hozzárendeli a gyökér View-t. A legtöbb projektben a loadView-hez nem nyúlk — a munka a viewDidLoad-ban történik.
A loadView felülírása csak speciális esetekben szükséges: amikor a teljes felület kóddal, Storyboard nélkül készül, vagy amikor a gyökér View-nak nem szabványos osztályból kell származnia. Az Apple azt ajánlja, hogy felülíráskor ne hívja a super.loadView-t — teljes mértékben átveszi a View létrehozását.
override func loadView() {
view = UIView()
view.backgroundColor = .white
}
viewDidLoad — a ciklus leggyakrabban használt metódusa. Egyszer hívódik meg, miután a View betöltődött a memóriába, de még nem jelent meg a képernyőn. Itt konfigurálják a subviews-okat, töltik fel a táblázatokat adatokkal, regisztrálják a cellákat és iratkoznak fel azokra az értesítésekre, amelyek a vezérlő teljes élettartama alatt aktívak.
Fontos jellemző: a viewDidLoad a képernyő újboli megjelenésekor nem hívódik újra. Ha minden megjelenésnél frissíteni kell az adatokat — használja a viewWillAppear-t. A viewDidLoad-ba csak azokat az egyszeri műveleteket helyezze, amelyektől az alapkonfiguráció függ.
viewWillAppear minden alkalommal közvetlenül azelőtt hívódik, hogy a View láthatóvá válik a felhasználó számára. Ez a metódus megkapja az animated paramétert, amely jelzi, hogy a megjelenés animációval történik-e. Itt frissítik az adatokat, töltik újra a táblázatokat, konfigurálják a NavigationBar-t, és rejtik vagy mutatják az elemeket az alkalmazás állapotától függően.
Használja a viewWillAppear-t az állapot szinkronizálására a képernyők között: ha a felhasználó módosíthatta az adatokat az előző képernyőn, ez a metódus a megfelelő hely a felület frissítésére. Minden viewWillAppear hívás megelőzi a képernyő megjelenését, még a gyermekvezérlőtől való visszatéréskor is.
viewDidAppear jelzi, hogy a View teljesen megjelent a képernyőn, és az átmeneti animációk befejeződtek. Ebben a pillanatban a képernyő kész az interakcióra — a felhasználó látja a teljes felületet és dolgozhat vele. Ez a metódus alkalmas a megjelenés után induló animációk elindítására, időzítők elindítására és analitikai megjelenítések követésére.
Ellentétben a viewWillAppear-ral, a viewDidAppear garantálja, hogy a képernyő nem csak látható, hanem teljesen kirenderelt. Ha animációt indít a viewWillAppear-ban, néhány képkocka kimaradhat, mert az UIKit még nem fejezte be az átmenetet. A sima animációkhoz használja a viewDidAppear-t.
viewWillDisappear a View képernyőről való eltűnése előtt hívódik — másik vezérlőre váltáskor, modális ablak bezárásakor vagy az alkalmazás minimalizálásakor. Ez a megfelelő hely az állapot mentésére, az értesítésekről való leiratkozásra, az aktív folyamatok leállítására és azon erőforrások felszabadítására, amelyekre nincs szükség, amikor a képernyő nem látható.
Fontos megjegyezni: a viewWillDisappear nem garantálja, hogy a View végül eltűnik — a gesztus megszakítható. Ezért a kritikus adatokat mentse el a viewDidDisappear-ban is, amely csak a tényleges eltűnés után hívódik meg.
viewDidDisappear befejezi a megjelenés és eltűnés ciklusát. Miután a View már elrejtődött a képernyőről, hívódik meg. Ebben a metódusban végleg leállítják az animációkat, eltávolítják az ideiglenes objektumokat, és megerősítik a viewWillDisappear-ban megkezdett adatmentést.
Ez a metódus megelőzi a vezérlő deinit-jét is — ha a UIViewController megsemmisül, a viewDidDisappear lesz az utolsó Lifecycle metódus a deinit hívása előtt. Használja a végső tisztításhoz, amelynek az objektum megsemmisítése előtt kell megtörténnie.
A meghívás sorrendje attól függ, hogy a képernyő hogyan jelenik meg: első alkalommal, visszatéréskor vagy modális megjelenítéskor. Nézzünk három fő forgatókönyvet az UIKit szemszögéből.
A képernyő első megjelenésekor az UIKit végigmegy a teljes létrehozási cikluson: meghívódik a loadView, majd a viewDidLoad, ezt követően elindul a megjelenési animáció. Az animáció során meghívódik a viewWillAppear, a befejezés után pedig a viewDidAppear. Ez az egyetlen forgatókönyv, amelyben minden metódus a loadView-tól a viewDidAppear-ig egymást követve hívódik.
override func viewDidLoad() {
super.viewDidLoad()
print("viewDidLoad — View betöltve a memóriába")
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
print("viewWillAppear — hamarosan megjelenik")
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
print("viewDidAppear — képernyő teljesen látható")
}
Amikor a felhasználó visszatér az előző képernyőre, az UIKit nem hívja újra a viewDidLoad-ot — a View már betöltődött a memóriába. Ehelyett a visszatérő képernyőn csak a viewWillAppear és viewDidAppear aktiválódik, a jelenlegin pedig a viewWillDisappear és viewDidDisappear. loadView és viewDidLoad kimarad, mert a képernyő már létezik a navigációs veremben.
Modális megjelenítés ugyanazokat a szabályokat követi: az új vezérlőnél a teljes ciklus lefut az első megjelenéskor, a jelenleginél pedig a viewWillDisappear és viewDidDisappear. Dismiss esetén a sorrend fordított: a visszatérő vezérlőnél újra aktiválódik a viewWillAppear és viewDidAppear, az elrejtettnél pedig a befejező metódusok. Ez a viselkedés egységes az UIKit összes átmeneti típusánál.
Nézzünk négy kulcsfontosságú forgatókönyvet, ahol a Lifecycle megértése közvetlenül befolyásolja a kód minőségét és a felhasználói élményt. Minden forgatókönyvhez példát és ajánlásokat adunk.
viewDidLoad — a hely a kezdeti konfigurációhoz, amely nem függ a képernyő láthatóságától. Itt konfigurálják a collectionView-t, regisztrálják a nib-fájlokat a cellákhoz, létrehozzák a data source-t és a layout-ot. Ha adatokat tölt be a hálózatról, a viewDidLoad-ban jobb csak elindítani a kérést, a felületet pedig a viewWillAppear-ban frissíteni, amikor a képernyő kész a megjelenítésre.
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(
MyCell.self,
forCellReuseIdentifier: MyCell.identifier
)
viewModel.loadInitialData()
}
Használja a viewWillAppear-t az adatok szinkronizálására minden képernyőmegjelenéskor. Például, ha a felhasználó módosíthatta a beállításokat az előző képernyőn, itt frissülnek a megjelenített értékek, újratöltődik a tábla és korrigálódik a NavigationBar állapota. Ez biztosítja, hogy a képernyő mindig aktuális adatokat mutasson bármilyen navigációs forgatókönyv esetén.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
tableView.reloadData()
navigationController?.setNavigationBarHidden(false, animated: animated)
}
viewDidAppear ideális azon animációk elindítására, amelyeknek azután kell kezdődniük, hogy a felhasználó látta a képernyőt. Itt küldik el az analitikai eseményeket is: képernyő megjelenítése, onboarding indítása vagy videólejátszás kezdete. Az animációk elindítása az átmenet befejeződése előtt rángatódó felülethez vezet — az UIKit nem tud elegendő képkockát előkészíteni.
A viewWillDisappear-ban mentik a piszkozatokat, állítják le az időzítőket és iratkoznak le a NotificationCenter-ről. Ez az utolsó pillanat, amikor a képernyő még látható és elérhető a felhasználói kontextust igénylő műveletek számára. A kritikus adatokhoz kiegészítőként a viewDidDisappear-t használják biztosítékként a megszakított gesztusok ellen.
Az életciklus metódusainak helytelen használata az iOS-alkalmazások egyik leggyakoribb hibáforrása. Nézzük a főbb hibákat, amelyeket a fejlesztők a UIViewController használatának különböző szakaszaiban elkövetnek.
Első hiba — subviews létrehozása init-ben vagy loadView-ban Storyboard használata esetén. Ha Interface Builder-t használ, ne írja felül a loadView-t szükségtelenül. A View loadView-ban történő létrehozása meglévő storyboard esetén az xib-fájl figyelmen kívül hagyásához és üres képernyőhöz vezet.
Második hiba — billentyűzetértesítésekre való feliratkozás viewDidLoad-ban leiratkozás nélkül. Ha feliratkozott a UIResponder.keyboardWillShowNotification-ra, de nem iratkozott le a képernyő elrejtésekor, a blokk a vezérlő deinit-je után is meghívódik — ez memóriaszivárgás az alkalmazás potenciális összeomlásával.
Harmadik hiba — időzítők és hálózati kérések, amelyek a képernyő megjelenése előtt indulnak. Képek betöltése vagy animációk végrehajtása, amikor a View még nem látható — erőforrások pazarlása. Helyezze át a vizuális frissítéseket a viewWillAppear-ba vagy viewDidAppear-ba.
Negyedik hiba — adatok mentése csak a viewWillDisappear-ban. Az interaktív pop gesztusnál a felhasználó elkezdhet egy húzást és megszakíthatja — a metódus meghívódott, de a képernyő nem tűnt el. Duplázza meg a kritikus mentést a viewDidDisappear-ban vagy az applicationDidEnterBackground handlerben.
Gyakran Ismételt Kérdések
Egyszer — a View memóriába történő betöltése után. A képernyő újboli megjelenésekor a viewDidLoad nem hívódik meg. Ha újra létre kell hozni a View-t, a vezérlőt meg kell semmisíteni és újra létrehozni.
Az UIKit megköveteli a super.viewDidLoad meghívását az életciklus helyes működéséhez. Enélkül problémák merülhetnek fel a layout frissítésével és az átmenetek kezelésével. Mindig a super-t hívja meg elsőként a metódusban.
Nem ajánlott. Ha a vezérlőt Storyboard-ból inicializálják, az UIKit automatikusan betölti a View-t az xib-ből. A loadView felülírása megszakítja ezt a folyamatot és a storyboard figyelmen kívül marad.
Iratkozzon fel a viewDidLoad-ban vagy viewWillAppear-ban, és iratkozzon le a viewWillDisappear-ban vagy viewDidDisappear-ban, gyenge referenciát használva a self-re a memóriaszivárgás elkerülése érdekében a closure-okban.
A Force quit kényszerítve öli meg a folyamatot — az UIKit nem ér rá, hogy meghívja a Lifecycle metódusokat. Az adatok mentéséhez használja az UIApplication.willTerminateNotification értesítést az AppDelegate-ben.
Összefoglaló
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is