viewWillDisappear je metoda UIViewController, kterou UIKit volá bezprostředně před tím, než obrazovka začne mizet z displeje uživatele. Podle Apple Developer Documentation tato metoda přijímá parametr animated a spouští se při push, pop, present, dismiss a přepínání karet. viewWillDisappear je hlavní místo pro ukládání stavu a správné čištění zdrojů.
Hlavní body
viewWillDisappear je metoda UIViewController, kterou UIKit volá bezprostředně před tím, než View ovladače začne mizet z obrazovky. V tomto okamžiku je obrazovka stále viditelná pro uživatele, ale přechod již byl zahájen: NavigationController spustil animaci push/pop, modální okno se začalo zavírat nebo TabBar začal přepínat na jinou kartu. Vývojář přepíše tuto metodu pro provádění operací, které vyžadují, aby obrazovka byla stále dostupná, ale již se připravuje na skrytí.
Na rozdíl od viewDidDisappear, které se spouští po skrytí obrazovky, viewWillDisappear poskytuje poslední šanci uložit data a uvolnit zdroje, zatímco uživatel stále vidí rozhraní. To je kritické pro UX — uložení konceptu nebo zastavení časovače musí nastat dříve, než uživatel přepne na jinou obrazovku.
Metoda přijímá parametr animated, který udává, zda zmizení probíhá s animací. Hodnota true znamená, že UIKit provádí přechod s animací, false — obrazovka mizí okamžitě, například při dismiss bez animace nebo programovém odstranění z hierarchie.
viewWillDisappear je voláno ve všech scénářích, kdy aktuální obrazovka přestává být aktivní. Podívejme se na hlavní případy specifické pro vývoj iOS.
Když UINavigationController provede push nového ovladače, u aktuálního ovladače je viewWillDisappear voláno na začátku přechodové animace. V tomto okamžiku je aktuální obrazovka stále viditelná pod novým ovladačem, který po ní klouže. Toto je standardní scénář, ve kterém se viewWillDisappear spouští s animated = true.
Když uživatel stiskne tlačítko zpět nebo provede interaktivní gesto přejetí zpět, u aktuálního ovladače je viewWillDisappear voláno. Při interaktivním gestu může být toto volání zrušeno, pokud si uživatel rozmyslí a vrátí obrazovku na místo. To je důležitá vlastnost, kterou je třeba zohlednit při navrhování ukládání stavu.
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
saveDraftData()
NotificationCenter.default.removeObserver(self)
}
Při zavírání modálního okna je viewWillDisappear voláno na zavíraném ovladači na začátku animace dismiss. V tomto okamžiku lze výsledky předat zpět prostřednictvím delegáta nebo closure, protože ovladač, který modální okno předložil, ještě nezískal řízení.
UITabBarController volá viewWillDisappear na ovladači opouštěné karty ihned po dotyku jiné karty uživatelem. Pokud na aktuální kartě probíhají aktivní procesy — přehrávání médií, načítání souboru, časovač — zde jsou pozastaveny nebo zastaveny.
viewWillDisappear řeší konkrétní úkoly správy zdrojů a stavu. Podívejme se na klíčové scénáře s příklady kódu.
Nejdůležitější úkol viewWillDisappear — ukládání dat, která uživatel zadal nebo změnil na aktuální obrazovce. Koncepty zpráv, upravená pole formulářů, vybraná nastavení — to vše musí být uloženo dříve, než obrazovka zmizí. Pro trvalost použijte Core Data, UserDefaults nebo úložiště souborů.
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
guard hasUnsavedChanges else { return }
draftStorage.save(currentDraft)
}
NotificationCenter, KVO a Combine publishry, na které jste se přihlásili v viewWillAppear nebo viewDidLoad, musí být zrušeny v viewWillDisappear. Pokud tak neučiníte, oznámení budou přicházet na skrytou obrazovku, způsobovat aktualizace UI, které uživatel nevidí, nebo — hůře — pády kvůli odkazům na již uvolněné objekty.
Animace UIView spuštěné v viewDidAppear a časovače pracující přes Timer nebo DispatchSource musí být zastaveny v viewWillDisappear. Pokračující animace na skryté obrazovce spotřebovávají GPU a baterii bez jakéhokoli užitku pro uživatele. Zastavte je explicitně voláním invalidate u časovačů a removeAllAnimations u vrstev.
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
countdownTimer?.invalidate()
countdownTimer = nil
loadingIndicator.layer.removeAllAnimations()
}
Pokud byl ovladač otevřen pro získání výsledku — výběr prvku, zadání textu, potvrzení akce — viewWillDisappear je poslední okamžik, kdy původní ovladač stále existuje v zásobníku a může přijímat data. Zavolejte delegáta nebo closure před tím, než je voláno deinit.
Spolehlivé ukládání stavu obrazovky je jedním z nejobtížnějších úkolů ve vývoji iOS. viewWillDisappear je důležitý, ale ne jediný prvek strategie. Podívejme se na komplexní přístup.
Úroveň 1 — ukládání v viewWillDisappear. Rychlé ukládání lehkých dat, která by měla být k dispozici okamžitě po návratu. Vhodné pro stav UI: pozice posouvání, vybraný segment, text ve vstupních polích. Problém: při zrušeném interaktivním gestu pop dojde k uložení, i když uživatel zůstal na obrazovce — data se přepisují zbytečně.
Úroveň 2 — ukládání v viewDidDisappear. Duplikuje ukládání z první úrovně, ale spouští se až poté, co je obrazovka zaručeně skryta. To je pojistka proti zrušeným gestům. Pokud jste se však v viewWillDisappear již odhlásili z oznámení, viewDidDisappear může mít omezený přístup k některým datům.
Úroveň 3 — ukládání prostřednictvím oznámení aplikace. UIApplication.willResignActiveNotification a UIApplication.didEnterBackgroundNotification zachycují minimalizaci aplikace. Pokud uživatel aplikaci minimalizoval, viewWillDisappear nemuselo být voláno — ale ukládání prostřednictvím těchto oznámení zaručuje integritu dat při ukončení relace.
| Úroveň | Metoda/Oznámení | Spolehlivost | Použití |
|---|---|---|---|
| 1 | viewWillDisappear | Vysoká | Stav UI, koncepty |
| 2 | viewDidDisappear | Velmi vysoká | Kritická data |
| 3 | willResignActive | Maximální | Při minimalizaci |
Doporučení: pro kritická uživatelská data používejte kombinaci všech tří úrovní. Pro nekritický stav stačí první úroveň. Důležité je nepřepisovat stejná data opakovaně — použijte příznak dirty, který indikuje, že se data od posledního uložení změnila.
Zvláštní pozornost je třeba věnovat strategii pro CRUD obrazovky, kde uživatel zadává data. Na takových obrazovkách se nedoporučuje ukládat každé stisknutí klávesy v viewWillDisappear — to je nadbytečné. Použijte automatické ukládání se zpožděním (debounce) přes Timer a viewWillDisappear aplikujte pouze pro konečné vynucené uložení, pokud existují neuložené změny. Tento přístup vyvažuje výkon a bezpečnost dat.
Pro aplikace s Core Data je dalším opatřením volání saveContext v viewWillDisappear pouze při skutečných změnách v managed object context. Kontrola context.hasChanges před uložením zabraňuje zbytečným zápisům do persistent store a prodlužuje životnost baterie zařízení. Zkombinujte tuto kontrolu s globálním ukládáním v applicationDidEnterBackground.
Nesprávné použití viewWillDisappear může vést ke ztrátě dat, únikům paměti a nestabilnímu chování aplikace. Podívejme se na časté chyby vývojářů iOS.
První chyba — ukládání dat pouze v viewWillDisappear. Jak bylo diskutováno výše, při interaktivním gestu pop je metoda volána, i když obrazovka nezmizí. Pokud má ukládání vedlejší účinky — odesílání dat na server, změna stavu — může to vést k falešným spuštěním. Přidejte kontrolu isBeingDismissed nebo isMovingFromParent.
Druhá chyba — chybějící odhlášení z NotificationCenter. To je jeden z nejčastějších úniků paměti v iOS. Pokud jste se přihlásili v viewWillAppear k UIResponder.keyboardWillShowNotification, ale neodhlásili v viewWillDisappear, closure je nadále voláno. Při deinit ovladače bude closure odkazovat na uvolněný objekt — pád aplikace je zaručen.
Třetí chyba — provádění těžkých synchronních operací. Ukládání velkého objemu dat, zápis do Core Data nebo souborového systému v viewWillDisappear blokuje main thread. Pokud operace trvá déle než přechodová animace, UIKit pozastaví vlákno a rozhraní zamrzne . Přesuňte těžká ukládání do backendových front.
Čtvrtá chyba — zapomenutí zavolat super. Nevolání super.viewWillDisappear může narušit činnost UINavigationController a UITabBarController, které tuto metodu používají pro své interní stavy. Vždy volejte super první nebo poslední, podle dokumentace Apple.
Tento problém se zhoršuje na iOS s aktivním multitaskingem a přepínáním mezi aplikacemi. Pátá chyba — použití DispatchQueue.main.async po uložení v viewWillDisappear. Pokud asynchronně odešlete blok do hlavní fronty po volání super.viewWillDisappear, není zaručeno, že ovladač v době provedení bloku stále existuje. Vždy používejte slabé reference [weak self] uvnitř closures, abyste zabránili odkazování na uvolněnou paměť a předešli pádu aplikace.
Často kladené otázky
viewWillDisappear je voláno na začátku mizení, když je obrazovka stále viditelná. viewDidDisappear — poté, co je obrazovka zcela skryta a animace dokončena.
Použijte viewDidDisappear pro potvrzení uložení nebo kontrolujte vlastnosti isMovingFromParent a isBeingDismissed uvnitř viewWillDisappear, abyste zjistili, zda obrazovka skutečně zmizí.
Ano, rozhodně, pokud používáte bloky nebo selektory s self. ARC nespravuje předplatné NotificationCenter. V iOS 9+ pro bloky použijte slabou referenci a odhlaste se v viewWillDisappear.
Nijak — force quit nevolá metody Lifecycle. Pro zaručené uložení při ukončení aplikace použijte UIApplication.willTerminateNotification nebo ukládejte data v reálném čase při jejich změně.
Ano, při interaktivním gestu pop UIKit volá viewWillDisappear ihned po zahájení gesta. Pokud uživatel gesto zruší, obrazovka zůstává viditelná, ale metoda se již spustila. Vždy kontrolujte isMovingFromParent.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také