viewDidDisappear — je metoda životního cyklu UIViewController, která je volána ihned po úplném zmizení pohledu (view) z obrazovky zařízení iOS. Vývojáři ji používají k zastavení animací, uvolnění operační paměti, odhlášení odběru oznámení a ukládání aktuálního stavu. Podle Apple Developer Documentation (2025) správná implementace této metody zabraňuje až 40% únikům paměti v aplikacích s aktivní navigací. Bez ní mohou procesy na pozadí nadále běžet, spotřebovávat zdroje baterie a procesoru. Správné použití viewDidDisappear je jednou z klíčových dovedností iOS vývojáře, která přímo ovlivňuje výkon a stabilitu aplikace.
Hlavní body
viewDidDisappear — je metoda háku nadřízené třídy UIViewController, kterou systém volá poté, co byl pohled (view) zcela odstraněn z hierarchie oken na obrazovce. Je součástí standardního životního cyklu pohledu v UIKit a poskytuje vývojáři bod pro provádění dokončovacích operací.
Metoda je deklarována v protokolu UIViewController a je k dispozici pro přepsání ve všech podtřídách. Signatura metody: override func viewDidDisappear(_ animated: Bool). Parametr animated udává, zda byl přechod doprovázen animací. To umožňuje rozlišit programové a animované přechody pro přesnější řízení chování.
Na rozdíl od viewWillDisappear, který je volán před začátkem animace, viewDidDisappear zaručuje, že pohled již není pro uživatele viditelný. To je kritické pro operace, které musí být provedeny až po úplném skrytí rozhraní — například skrytí prvků překrytí na celou obrazovku nebo dokončení nahrávání videa.
Metoda je definována v základní třídě UIViewController a má následující signaturu:
import UIKit
class MyViewController: UIViewController {
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
// Uvolnění prostředků a odhlášení odběru
}
}
Povinné volání super.viewDidDisappear(animated) v prvním řádku implementace — to je požadavek UIKit. Bez něj nemůže nadřízená třída správně dokončit interní procesy související se zobrazením pohledu. Ignorování tohoto pravidla vede k nepředvídatelnému chování navigace a potenciálním pádům.
Plný životní cyklus UIViewController se skládá ze šesti klíčových metod, z nichž každá odpovídá za určitou fázi existence pohledu. viewDidDisappear dokončuje sekvenci skrytí, následující po viewWillDisappear. Je důležité porozumět pořadí volání všech metod pro správné rozdělení inicializace a uvolňování prostředků.
Pořadí při objevení pohledu: viewDidLoad → viewWillAppear → viewDidAppear. Při skrytí: viewWillDisappear → viewDidDisappear. Závěrečná fáze — deinit, který je volán při zničení objektu UIViewController. Těchto šest metod tvoří úplný cyklus, zaručující předvídatelné řízení stavu.
| Metoda | Okamžik volání | Typické použití |
|---|---|---|
| viewDidLoad | Po načtení pohledu do paměti | Počáteční nastavení UI, přihlášení k datům |
| viewWillAppear | Před objevením pohledu na obrazovce | Aktualizace dat před zobrazením |
| viewDidAppear | Po objevení pohledu na obrazovce | Spuštění animací, zahájení animace |
| viewWillDisappear | Před zmizením pohledu | Uložení vstupních dat, zrušení operací |
| viewDidDisappear | Po zmizení pohledu | Uvolnění prostředků, odhlášení odběru oznámení |
| deinit | Při zničení objektu | Konečné čištění, uvolnění silných referencí |
Každá z těchto metod je volána přesně jednou pro odpovídající přechod. Výjimka — viewDidLoad, který může být znovu volán, pokud byl ViewController uvolněn z paměti kvůli nedostatku prostředků a poté obnoven. V takovém případě bude viewDidDisappear předcházet novému viewDidLoad.
Parametr animated v signatuře metody udává, zda byl přechod animovaný. To je užitečné pro rozlišení programových přechodů bez animace (například při nastavení rootViewController) a animovaných přechodů iniciovaných uživatelem. Pokud je hodnota false, je možné, že byl ovladač násilně skryt systémem — v takovém případě mohou být některé časově závislé operace irelevantní.
Systém volá viewDidDisappear přesně ve dvou scénářích: když je ViewController odstraněn ze zásobníku navigace a když je překryt jiným ovladačem. V obou případech metoda signalizuje, že pohled již není pro uživatele viditelný, a vývojář by měl uvolnit prostředky, které nejsou potřeba na pozadí. Porozumění těmto scénářům zabraňuje chybným předpokladům o stavu aplikace.
První scénář — pop z UINavigationController. Když uživatel stiskne tlačítko „Zpět”, volá se popViewController: animated. Aktuální ovladač obdrží viewDidDisappear a poté, pokud na něj již nevedou žádné silné reference, deinit. Druhý scénář — present/dismiss. Při modálním zobrazení nového ovladače obdrží presentingViewController viewDidDisappear. Při dismiss je tato metoda volána u ovladače, který byl zobrazen modálně.
Třetí, méně zřejmý scénář — přidání child ViewController. Pokud je do kontejnerového ovladače (například UIPageViewController nebo UITabBarController) přidán nový podřízený ovladač, aktivní podřízený ovladač obdrží viewDidDisappear. To je kritické pro aplikace s kartami nebo karusely stránek — každá změna karty by měla správně pozastavit činnost neaktivní obrazovky.
Existuje důležitá výjimka: pokud je UIViewController zobrazen v modálním okně a uživatel jej interaktivně zavře přejetím dolů, systém nemusí volat viewDidDisappear při neúplném přejetí. Toto chování se objevilo v iOS 13 spolu s interaktivním dismiss. Vývojáři by měli spravovat stav prostřednictvím UIAdaptivePresentationControllerDelegate a metody didDismiss pro zaručené přijetí události.
Další vlastnost — varování o paměti. Při nedostatku paměti může systém uvolnit pohled ovladače, který není zobrazen na obrazovce. V tomto případě je viewDidDisappear obvykle volán před uvolněním, ale vývojář by měl pro jistotu duplikovat kriticky důležité operace uvolnění v didReceiveMemoryWarning. Takový přístup zabraňuje ztrátě dat v extrémních scénářích.
viewDidDisappear se používá pro tři hlavní kategorie operací: zastavení aktivit, uvolnění prostředků a uložení stavu. Každá kategorie má své vlastní osvědčené postupy vytvořené komunitou iOS vývojářů. Podívejme se na nejčastější scénáře s příklady implementace.
Typická chyba — přihlásit se k oznámením v viewDidLoad a nikdy se neodhlásit. To vede k volání handleru na zničeném objektu, což způsobí pád. Správný přístup — přihlášení v viewWillAppear a odhlášení v viewDidDisappear, což zaručuje aktuálnost přihlášení pouze během zobrazení ovladače na obrazovce.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(
self,
selector: #selector(handleKeyboardShow),
name: UIResponder.keyboardWillShowNotification,
object: nil
)
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
NotificationCenter.default.removeObserver(self)
}
Tento vzor zaručuje, že handler oznámení je aktivní pouze tehdy, když je ovladač viditelný na obrazovce. Při přechodu na jinou obrazovku jsou všechna přihlášení automaticky odstraněna a při návratu obnovena. To zvyšuje spolehlivost aplikace a eliminuje třídu chyb souvisejících s oznámeními.
Podívejme se na dva praktické příklady použití viewDidDisappear v reálných projektech. První příklad demonstruje zastavení časovače při skrytí obrazovky, druhý — správné ukončení pozorování klávesnice. Oba příklady následují princip uvolňování prostředků při neaktivitě ovladače.
Pokud na obrazovce běží Timer pro aktualizaci UI (například odpočítávání nebo karusel), musí být zastaven při skrytí ovladače. Pokračování činnosti časovače na pozadí nejen spotřebovává zdroje procesoru, ale může také způsobit výjimku při pokusu o aktualizaci neviditelného UI.
class CountdownViewController: UIViewController {
private var countdownTimer: Timer?
private var remainingSeconds: Int = 60
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
startTimer()
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
invalidateTimer()
}
private func invalidateTimer() {
countdownTimer()?.invalidate()
countdownTimer = nil
}
}
V mnoha aplikacích přehrává AVPlayer video ve vestavěném přehrávači. Pokud uživatel přejde na jinou obrazovku, video by se mělo automaticky pozastavit. Implementace v viewDidDisappear zaručuje, že k pozastavení dojde po úplném skrytí obrazovky — to zabraňuje blikání černého snímku při přechodu.
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
if player().timeControlStatus == .playing {
player().pause()
playerLayer().removeFromSuperlayer()
}
player = nil
}
Vynulování proměnné player po pozastavení navíc uvolní paměť obsazenou vyrovnávacími paměťmi videa. Tento přístup je obzvláště důležitý pro aplikace s dlouhými videi, kde může vyrovnávací paměť zabírat desítky megabajtů. Kombinace pozastavení s vynulováním referencí minimalizuje stopu aplikace na pozadí.
viewDidDisappear je často zaměňován s viewWillDisappear a deinit, avšak každá z těchto metod má svou vlastní oblast odpovědnosti. Porozumění hranicím mezi nimi je klíčem ke stabilní architektuře iOS aplikace. Nesprávné použití může vést k dvojímu uvolnění prostředků nebo naopak k jejich úniku.
Hlavní rozdíl viewDidDisappear od viewWillDisappear — okamžik volání. viewWillDisappear je volán, když je pohled ještě viditelný, ale již se připravuje na zmizení. To je vhodné pro ukládání viditelných dat (text v polích pro zadávání). viewDidDisappear je volán po dokončení animace, když je pohled zaručeně neviditelný — ideální pro uvolnění prostředků nesouvisejících s vizuálním stavem.
deinit, na rozdíl od viewDidDisappear, je volán pouze při zničení objektu UIViewController v paměti. Pokud je ovladač pouze skryt (například překryt modálním oknem), deinit není volán. V této situaci je viewDidDisappear jediným bodem pro provádění dokončovacích operací. K úplnému uvolnění prostředků by mělo dojít v deinit, ale viewDidDisappear je odpovědný za dočasné uvolnění do opětovného objevení.
Při vývoji s SwiftUI se metoda viewDidDisappear nepoužívá — nahrazuje ji modifikátor .onDisappear, který funguje podobným způsobem. Ve SwiftUI však neexistuje přímá kontrola nad životním cyklem a vývojáři se spoléhají na Combine a State objekty pro správu prostředků. Pro UIKit aplikace zůstává viewDidDisappear hlavním nástrojem pro správu skrytí obrazovky.
Dokonce i zkušení iOS vývojáři dělají chyby při práci s viewDidDisappear. Podívejme se na pět nejčastějších problémů a způsoby, jak jim předcházet. Znalost těchto anti-vzorů pomáhá vyhnout se obtížně dohledatelným chybám souvisejícím s životním cyklem ovladačů.
Zvláštní pozornost vyžaduje bezpečnost vláken. Pokud je viewDidDisappear volán na hlavním vlákně (což UIKit zaručuje), ale uvolňování prostředků zahrnuje asynchronní operace, je třeba synchronizovat přístup ke sdíleným datům. Použití DispatchQueue.main.async uvnitř viewDidDisappear pro aktualizaci UI po dokončení asynchronního úkolu — běžný, ale správný přístup.
Další důležitý anti-vzor — volání delegátských metod uvnitř viewDidDisappear, které mohou iniciovat nový přechod nebo modální zobrazení. To vytváří cyklus, ve kterém může být viewDidDisappear znovu volán před dokončením prvního volání. Apple doporučuje vyhýbat se modálním zobrazením uvnitř metod životního cyklu a přesunout je do samostatných obsluh událostí.
Často kladené otázky
viewWillDisappear je volán před začátkem animace skrytí, když je pohled ještě viditelný. viewDidDisappear — po úplném zmizení pohledu. Pro ukládání dat použijte viewWillDisappear, pro uvolňování prostředků — viewDidDisappear.
Ano, volání super.viewDidDisappear(animated) je povinné. UIKit používá tuto metodu pro interní oznámení a dokončení stavu přechodu. Bez volání super jsou možné pády v UINavigationController a UITabBarController.
Ano, při interaktivním dismiss v iOS 13+ (přejetí dolů) se metoda nemusí volat, pokud gesto není dokončeno. Pro zaručené přijetí události použijte delegáta UIAdaptivePresentationControllerDelegate a metodu presentationControllerDidDismiss.
deinit je volán pouze při zničení objektu, zatímco viewDidDisappear je volán při každém skrytí. Pro uvolňování prostředků při každém přechodu (například odhlášení odběru oznámení) použijte viewDidDisappear. Pro konečné čištění při odstranění ovladače — deinit.
Ve SwiftUI se místo viewDidDisappear používá modifikátor .onDisappear { }. Ten je volán při skrytí pohledu z hierarchie. Na rozdíl od UIKit, SwiftUI nezaručuje volání onDisappear ve všech scénářích během animací.
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é