A viewWillDisappear egy UIViewController metódus, amelyet a UIKit közvetlenül azelőtt hív meg, hogy a képernyő eltűnni kezd a felhasználó kijelzőjéről. A Apple Developer Documentation szerint ez a metódus fogadja az animated paramétert, és push, pop, present, dismiss valamint lapozáskor aktiválódik. viewWillDisappear a fő hely az állapot mentésére és az erőforrások megfelelő tisztítására.
Főbb pontok
viewWillDisappear egy UIViewController metódus, amelyet a UIKit közvetlenül azelőtt hív meg, hogy a vezérlő View-ja eltűnni kezd a képernyőről. Ebben a pillanatban a képernyő még látható a felhasználó számára, de az átmenet már elindult: a NavigationController elindította a push/pop animációt, a modális ablak elkezdett bezáródni, vagy a TabBar elkezdett egy másik lapra váltani. A fejlesztő felülírja ezt a metódust, hogy olyan műveleteket hajtson végre, amelyekhez a képernyőnek még elérhetőnek kell lennie, de már készül az elrejtésre.
Ellentétben a viewDidDisappear-rel, amely a képernyő elrejtése után aktiválódik, a viewWillDisappear utolsó lehetőséget biztosít az adatok mentésére és az erőforrások felszabadítására, amíg a felhasználó még látja a felületet. Ez kritikus fontosságú a UX szempontjából — a piszkozat mentésének vagy a időzítő leállításának meg kell történnie, mielőtt a felhasználó másik képernyőre vált.
A metódus fogadja az animated paramétert, amely jelzi, hogy az eltűnés animációval történik-e. A true érték azt jelenti, hogy a UIKit az átmenetet animációval hajtja végre, a false — a képernyő azonnal eltűnik, például animáció nélküli dismiss esetén vagy programozott eltávolításkor a hierarchiából.
viewWillDisappear minden olyan esetben meghívódik, amikor az aktuális képernyő megszűnik aktív lenni. Tekintsük át az iOS-fejlesztésre jellemző fő eseteket.
Amikor a UINavigationController push-ol egy új vezérlőt, az aktuális vezérlőn a viewWillDisappear az átmenet animáció elején hívódik meg. Ebben a pillanatban az aktuális képernyő még látható az új, fölötte csúszó vezérlő alatt. Ez az a standard eset, amikor a viewWillDisappear animated = true paraméterrel aktiválódik.
Amikor a felhasználó megnyomja a vissza gombot vagy interaktív visszahúzó gesztust végez, az aktuális vezérlőn meghívódik a viewWillDisappear. Interaktív gesztus esetén ez a hívás megszakítható, ha a felhasználó meggondolja magát és visszahelyezi a képernyőt. Ez egy fontos tulajdonság, amelyet figyelembe kell venni az állapotmentés tervezésekor.
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
saveDraftData()
NotificationCenter.default.removeObserver(self)
}
A modális ablak bezárásakor a viewWillDisappear a bezáruló vezérlőn hívódik meg a dismiss animáció elején. Ebben a pillanatban az eredmények visszaküldhetők delegátumon vagy closure-on keresztül, mivel a modális ablakot megjelenítő vezérlő még nem kapta meg a vezérlést.
Az UITabBarController meghívja a viewWillDisappear-t az elhagyott lap vezérlőjén közvetlenül azután, hogy a felhasználó megérintett egy másik lapot. Ha az aktuális lapon aktív folyamatok vannak — média lejátszás, fájl betöltés, időzítő — itt szüneteltetik vagy állítják le őket.
viewWillDisappear konkrét feladatokat old meg az erőforrás- és állapotkezelés terén. Tekintsük át a főbb eseteket kódpéldákkal.
A viewWillDisappear legfontosabb feladata — azon adatok mentése, amelyeket a felhasználó az aktuális képernyőn megadott vagy módosított. Üzenetpiszkozatok, szerkesztett űrlapmezők, kiválasztott beállítások — mindezt menteni kell, mielőtt a képernyő eltűnik. Az adatok tartósságához használjon Core Data-t, UserDefaults-t vagy fájl tárolót.
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
guard hasUnsavedChanges else { return }
draftStorage.save(currentDraft)
}
NotificationCenter, KVO és Combine publisher-ek, amelyekre a viewWillAppear-ben vagy viewDidLoad-ban feliratkozott, törlendők a viewWillDisappear-ben. Ha ezt nem teszi meg, az értesítések a rejtett képernyőre érkeznek, ami olyan UI-frissítéseket okoz, amelyeket a felhasználó nem lát, vagy ami rosszabb — összeomlást a már felszabadított objektumokra való hivatkozások miatt.
A viewDidAppear-ben elindított UIView animációk és a Timer vagy DispatchSource segítségével működő időzítők leállítandók a viewWillDisappear-ben. A rejtett képernyőn folytatódó animációk GPU-t és akkumulátort fogyasztanak a felhasználó számára nyújtott előny nélkül. Állítsa le őket explicit módon az időzítőknél invalidate, a rétegeknél removeAllAnimations hívással.
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
countdownTimer?.invalidate()
countdownTimer = nil
loadingIndicator.layer.removeAllAnimations()
}
Ha a vezérlőt eredmény elérése érdekében nyitották meg — elem kiválasztása, szöveg bevitele, művelet megerősítése — a viewWillDisappear az utolsó pillanat, amikor az eredeti vezérlő még létezik a veremben és fogadhat adatokat. Hívja meg a delegátumot vagy closure-t azelőtt, hogy a deinit meghívódna.
A képernyő állapotának megbízható mentése az iOS-fejlesztés egyik legnehezebb feladata. A viewWillDisappear fontos, de nem az egyetlen eleme a stratégiának. Tekintsünk át egy átfogó megközelítést.
1. szint — mentés a viewWillDisappear-ben. Könnyű adatok gyors mentése, amelyeknek a visszatérés után azonnal elérhetőnek kell lenniük. Alkalmas UI-állapotra: görgetési pozíció, kiválasztott szegmens, szöveg a beviteli mezőkben. Probléma: megszakított interaktív pop gesztusnál a mentés akkor is megtörténik, ha a felhasználó a képernyőn maradt — az adatok szükségtelenül felülíródnak.
2. szint — mentés a viewDidDisappear-ben. Az első szint mentését duplikálja, de csak azután aktiválódik, hogy a képernyő garantáltan el lett rejtve. Ez biztosíték a megszakított gesztusok ellen. Ha azonban a viewWillDisappear-ben már leiratkozott az értesítésekről, a viewDidDisappear nem férhet hozzá bizonyos adatokhoz.
3. szint — mentés alkalmazásértesítéseken keresztül. Az UIApplication.willResignActiveNotification és UIApplication.didEnterBackgroundNotification elfogja az alkalmazás minimalizálását. Ha a felhasználó minimalizálta az alkalmazást, a viewWillDisappear nem hívódott meg — de az értesítéseken keresztüli mentés garantálja az adatok integritását a munkamenet végén.
| Szint | Metódus/Értesítés | Megbízhatóság | Használat |
|---|---|---|---|
| 1 | viewWillDisappear | Magas | UI-állapot, piszkozatok |
| 2 | viewDidDisappear | Nagyon magas | Kritikus adatok |
| 3 | willResignActive | Maximális | Minimalizáláskor |
Ajánlás: használja mindhárom szint kombinációját a kritikus felhasználói adatokhoz. Nem kritikus állapothoz az első szint elegendő. Fontos, hogy ne írja felül ugyanazokat az adatokat többször — használjon dirty jelzőt, amely jelzi, hogy az adatok megváltoztak az utolsó mentés óta.
Különös figyelmet kell fordítani a CRUD-képernyők stratégiájára, ahol a felhasználó adatokat visz be. Az ilyen képernyőkön nem ajánlott minden billentyűleütést menteni a viewWillDisappear-ben — ez felesleges. Használjon automatikus mentést késleltetéssel (debounce) Timer segítségével, és a viewWillDisappear-t csak a végső kényszerített mentésre alkalmazza, ha vannak nem mentett változtatások. Ez a megközelítés egyensúlyt teremt a teljesítmény és az adatbiztonság között.
A Core Data-val rendelkező alkalmazások esetében további intézkedés a saveContext meghívása a viewWillDisappear-ben csak akkor, ha tényleges változások történtek a managed object context-ben. A context.hasChanges ellenőrzése a mentés előtt megakadályozza a szükségtelen írásokat a persistent store-ba és meghosszabbítja az eszköz akkumulátorának élettartamát. Kombinálja ezt az ellenőrzést a globális mentéssel az applicationDidEnterBackground-ben.
A viewWillDisappear helytelen használata adatvesztéshez, memóriaszivárgáshoz és az alkalmazás instabil viselkedéséhez vezethet. Tekintsük át az iOS-fejlesztők gyakori hibáit.
Első hiba — adatok mentése csak a viewWillDisappear-ben. Ahogy fentebb tárgyaltuk, interaktív pop gesztusnál a metódus akkor is meghívódik, ha a képernyő nem tűnik el. Ha a mentés mellékhatásokkal jár — adatok küldése a szerverre, állapotváltoztatás — ez hamis aktiválásokhoz vezethet. Adjon hozzá isBeingDismissed vagy isMovingFromParent ellenőrzést.
Második hiba — a NotificationCenter-ről való leiratkozás elmulasztása. Ez az egyik leggyakoribb memóriaszivárgás iOS-ben. Ha a viewWillAppear-ben feliratkozott az UIResponder.keyboardWillShowNotification-ra, de nem iratkozott le a viewWillDisappear-ben, a closure továbbra is hívódik. A vezérlő deinit-jekor a closure egy felszabadított objektumra hivatkozik — az alkalmazás összeomlása garantált.
Harmadik hiba — nehéz szinkron műveletek végrehajtása. Nagy mennyiségű adat mentése, Core Data-ba vagy fájlrendszerbe írás a viewWillDisappear-ben blokkolja a main thread-et. Ha a művelet hosszabb ideig tart, mint az átmenet animációja, a UIKit felfüggeszti a szálat és a felület lefagy. Helyezze át a nehéz mentéseket háttérvárólistákra.
Negyedik hiba — elfelejtik meghívni a super-t. A super.viewWillDisappear elmulasztása megzavarhatja a UINavigationController és UITabBarController működését, amelyek ezt a metódust használják belső állapotaikhoz. Mindig hívja meg a super-t elsőként vagy utolsóként, az Apple dokumentációja szerint.
Ez a probléma súlyosbodik iOS-en az aktív multitasking és az alkalmazások közötti váltogatás miatt. Ötödik hiba — a DispatchQueue.main.async használata a viewWillDisappear-ben történő mentés után. Ha a super.viewWillDisappear meghívása után aszinkron blokkot küld a fő várólistába, nincs garancia arra, hogy a vezérlő még létezik a blokk végrehajtásának pillanatában. Mindig használjon gyenge referenciákat [weak self] a closure-okon belül, hogy megakadályozza a felszabadított memóriára való hivatkozást és az alkalmazás összeomlását.
Gyakran ismételt kérdések
viewWillDisappear az eltűnés elején hívódik meg, amikor a képernyő még látható. viewDidDisappear — miután a képernyő teljesen elrejtődött és az animáció befejeződött.
Használja a viewDidDisappear-t a mentés megerősítéséhez, vagy ellenőrizze az isMovingFromParent és isBeingDismissed tulajdonságokat a viewWillDisappear-ben annak megállapításához, hogy a képernyő tényleg eltűnik-e.
Igen, kötelező, ha blokkokat vagy szelektorokat használ self-fel. Az ARC nem kezeli a NotificationCenter feliratkozásokat. iOS 9+ esetén blokkokhoz használjon gyenge referenciát és iratkozzon le a viewWillDisappear-ben.
Sehogy — a force quit nem hívja meg a Lifecycle metódusokat. Garantált mentéshez az alkalmazás befejezésekor használja az UIApplication.willTerminateNotification-t, vagy mentse az adatokat valós időben, ahogy változnak.
Igen, interaktív pop gesztusnál a UIKit a viewWillDisappear-t közvetlenül a gesztus megkezdése után hívja. Ha a felhasználó megszakítja a gesztust, a képernyő látható marad, de a metódus már aktiválódott. Mindig ellenőrizze az isMovingFromParent-t.
Összefoglalás
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