.onDisappear — egy SwiftUI-módosító, amely egy lezárást hajt végre, amikor egy View eltávolításra kerül az interfész hierarchiájából. A hívás a képernyő bezárásakor, lap váltásakor, modális ablak elutasításakor vagy egy elem látható területen kívülre görgetésekor történik. Az Apple Developer Documentation (2026) szerint az onDisappear nem garantálja a hívást vészhelyzeti megszakítás vagy az alkalmazás system-watchdog általi megsemmisítése esetén. További információ a SwiftUI-ról a SwiftUI anyagában olvasható.
Főbb pontok
.onDisappear — egy View-módosító a SwiftUI-ban, amely egy Void lezárást fogad el és végrehajtja, amikor a View eltávolításra kerül a hierarchiából. Az .onAppear-rel párban alkotja a képernyő teljes életciklusát: megjelenés — működés — eltűnés. Az Apple az onDisappeart a SwiftUI iOS 13-as megjelenésével együtt vezette be az UIKit viewDidDisappear analógjaként.
Szintaktikailag .onDisappear megegyezik az onAppearrel: bármely View-t módosít, és egy lezárást csatol, amelyet a SwiftUI komponens hív meg a nézet eltávolításakor. Az UIKit-től eltérően, ahol a viewDidDisappear csak az átmeneti animáció befejezése után aktiválódik, az onDisappear SwiftUI-ban az animáció befejezése előtt is meghívható — abban a pillanatban, amikor a View eltávolításra van jelölve.
Alap szintaxis az onDisappear ugyanolyan tömör, mint az onAppear. A módosító nem fogad el további paramétereket — csak a lezárást, amely szinkron módon a fő szálon hajtódik végre.
struct DetailView: View {
var body: some View {
Text("Részlet Képernyő")
.onDisappear {
print("DetailView eltűnt a képernyőről")
}
}
}
A hívás mechanizmusa az onDisappear ellentéte az onAppearnek: először a gyermek elemek kapják meg az onDisappeart, majd a szülő. Ez a child-first szabály garantálja, hogy a gyermek elemek erőforrásai a szülő erőforrásainak felszabadítása előtt szabadulnak fel. Ha egy gyermek elem függ a szülő adataitól, képesnek kell lennie a szülő kontextus nélküli helyes befejeződésre.
SwiftUI az onDisappeart abban a pillanatban hívja meg, amikor a View kikerül a renderelési gráfból. Kiváltó ok lehet: pop a NavigationStackből, TabView váltása, modális ablak elutasítása (sheet/fullScreenCover), feltételesen megjelenített View változása (if/switch). Listában és ScrollViewban az onDisappear akkor hívódik, amikor egy cella a prefetch pufferén kívülre görget.
Child-first sorrend azt jelenti, hogy ha három gyermek View van egy VStackben, az onDisappear először minden gyermekre fordított sorrendben hívódik, majd a szülőre. Ez kritikus a helyes tisztításhoz: a gyermek időzítők törlésre kerülnek, mielőtt a szülő ViewModel felszabadítaná a megosztott erőforrásokat.
struct ParentView: View {
var body: some View {
VStack {
ChildView(id: "A")
ChildView(id: "B")
}
.onDisappear {
print("Parent onDisappear — utolsó")
}
}
}
struct ChildView: View {
let id: String
var body: some View {
Text("Gyermek \(id)")
.onDisappear {
print("Gyermek \(id) onDisappear")
}
}
}
Konzol kimenet: Child B onDisappear, Child A onDisappear, Parent onDisappear — utolsóként. Az onAppearhez képest fordított sorrend garantálja a helyes felszabadítási láncot.
A hívás forgatókönyvei az onDisappear a tároló típusától függenek. NavigationStackben az onDisappear pop-to-root, szokásos pop-back vagy a képernyő húzással történő eltávolításakor (interactivePopGestureRecognizer) aktiválódik. TabViewben a lapváltás onDisappeart vált ki az elrejtett lapra és onAppeart a megjelenítettre — mindkét módosító szinte egyidejűleg aktiválódik.
Sheetben és fullScreenCoverben az onDisappear programozott elutasításkor (az @Environment(\.dismiss) segítségével) vagy lefelé húzó gesztussal hívódik meg. Fontos jellemző: ha a sheet meg volt nyitva, de a felhasználó alkalmazást váltott, az onDisappear NEM hívódik meg a tényleges bezárásig.
| Forgatókönyv | onDisappear meghívódik | Megjegyzés |
|---|---|---|
| Pop a NavigationStackben | Igen | Az animáció után azonnal |
| TabView lap váltás | Igen | Aktuális lap |
| Sheet elutasítása | Igen | Az animáció befejezése előtt |
| Görgetés Listában | Igen | Cella elhagyta a prefetch zónát |
| Alkalmazás minimalizálása | Nem | Nincs garancia a hívásra |
| Crash/watchdog kill | Nem | Nem hívódik meg |
Fő forgatókönyvek az onDisappear — erőforrások tisztítása, állapot mentése és nyomon követés. Az onAppeartől eltérően az onDisappear feladatok kilépéskor hajtódnak végre, és nem igényelnek ismétlődés ellenőrzést, mivel a View egyszer tűnik el.
Állapot mentése az onDisappearben különösen hasznos olyan űrlapok esetén, ahol az adatokat a képernyő elhagyásakor kell menteni. Az időzítők és Combine feliratkozások az onDisappearben törlődnek, hogy elkerüljék a memóriaszivárgást a képernyőre való visszatéréskor.
struct FormView: View {
@State private var draftText = ""
@State private var timer: Timer?
var body: some View {
TextField("Enter text", text: $draftText)
.onAppear {
timer = Timer.scheduledTimer(withTimeInterval: 60, repeats: true) { _ in
saveDraft()
}
}
.onDisappear {
timer?.invalidate()
timer = nil
saveDraft()
}
}
private func saveDraft() {
UserDefaults.standard.set(draftText, forKey: "draft")
}
}
Időzítő törlése az onDisappearben megakadályozza a kód végrehajtását a képernyő bezárása után. Törlés nélkül az időzítő megpróbálhat frissíteni egy @State-et, amely már nem tartozik az aktuális View-hoz, futásidejű figyelmeztetést okozva.
Tartózkodási idő a képernyőn — klasszikus nyomon követési forgatókönyv. Rögzítjük az időt az onAppearben, kiszámítjuk a különbséget az onDisappearben, és analitikai eseményt küldünk a munkamenet időtartamával.
struct TrackedView: View {
@State private var appearTime: Date?
var body: some View {
Text("Követett Képernyő")
.onAppear {
appearTime = Date()
Analytics.shared.logEvent("screen_view", params: ["screen": "TrackedView"])
}
.onDisappear {
if let start = appearTime {
let duration = Date().timeIntervalSince(start)
Analytics.shared.logEvent("screen_close", params: [
"screen": "TrackedView",
"duration_ms": Int(duration * 1000)
])
}
}
}
}
Fő különbség az onDisappear és az onAppear között — a hívás sorrendje és az aktiválási garanciák. Az onAppear akkor hívódik, amikor a View hozzáadásra kerül a hierarchiához, és újrahívási tulajdonsággal rendelkezik újbóli létrehozáskor. Az onDisappear eltávolításkor hívódik, és csak normál bezáráskor garantáltan működik, de vészhelyzeti forgatókönyvek esetén nem.
A WWDC 2024 szerint az Apple azt ajánlja, hogy az onDisappeart tisztítási pontként kezeljék, nem adatmentési pontként. A kritikus fontosságú adatokat (fizetések, regisztrációk) valós időben kell menteni, nem a View eltűnésének pillanatában, mivel az onDisappear nem garantálja a hívást az alkalmazás minimalizálásakor.
| Jellemző | .onAppear | .onDisappear |
|---|---|---|
| Hívás pillanata | View hozzáadása hierarchiához | View eltávolítása hierarchiából |
| Sorrend | Parent-first | Child-first |
| Garancia | Magas | Nincs vészhelyzeti megszakításnál |
| Fő feladat | Inicializálás | Tisztítás |
| Újrahívás | A View újbóli létrehozásakor | Egyszeri eltűnésenként |
Javaslat: az onDisappeart csak nem kritikus tisztításhoz és nyomon követéshez használja. Adatok mentéséhez használja a scenePhase-t vagy az applicationWillTerminate értesítéseket az AppDelegate-ben.
1. forgatókönyv: YouTube-szerű betöltés. A videó részletei képernyőn az onDisappear elmenti a lejátszási pozíciót a UserDefaultsba. Újbóli megnyitáskor az onAppear visszaállítja a pozíciót a UserDefaultsból, folyamatos nézési hatást keltve.
2. forgatókönyv: Combine feliratkozás törlése. Ha a ViewModel Combine kiadókat használ, az onDisappear törli a feliratkozást a cancellable?.cancel() segítségével. Ez megakadályozza a UI frissítését a képernyő elhagyása után, ami különösen fontos lapozható listák és keresési lekérdezések esetén.
3. forgatókönyv: WebSocket bezárása. Valós idejű kapcsolatokkal rendelkező alkalmazásokban (üzenetküldők, árfolyam hírcsatornák) az onDisappear bezárja a WebSocket kapcsolatot az akkumulátor és a forgalom megtakarítása érdekében. Az újbóli megnyitás az onAppearben történik a képernyőre való visszatéréskor.
WebSocket — tipikus erőforrás, amelyet be kell zárni a képernyő elhagyásakor. Az alábbi példában az onDisappear bontja a socketet, az onAppear pedig újracsatlakoztatja, ami jelentős forgalom megtakarítást eredményez a több képernyős alkalmazások számára.
struct ChatView: View {
@StateObject private var socket = WebSocketManager()
var body: some View {
ChatListView(messages: socket.messages)
.onAppear {
socket.connect()
}
.onDisappear {
socket.disconnect()
}
}
}
Fontos: a TabView lapjai közötti váltáskor az aktuális lap onDisappear és a következő lap onAppear szinte egyszerre aktiválódik. WebSocket esetén ez disconnect-connect ciklushoz vezethet, amely többletterhelést okoz. Megoldás — késleltetés használata vagy annak ellenőrzése, hogy szükség van-e a socketre a következő képernyőn.
Gyakran Ismételt Kérdések
Igen, az .onDisappear nem garantálja a hívást az alkalmazás vészhelyzeti megszakításakor (crash, watchdog kill), az alkalmazás képernyő bezárása nélküli minimalizálásakor, vagy olyan rendszerforgatókönyv esetén, amikor az alkalmazás a háttérben megsemmisül. Kritikus fontosságú adatokhoz használja a scenePhase-t vagy az applicationWillTerminate-t.
.onDisappear akkor aktiválódik, amikor egy View eltávolításra kerül a hierarchiából — egy helyi visszahívás egy adott képernyőhöz. .scenePhase (az @Environment(\.scenePhase) segítségével) akkor aktiválódik, amikor a teljes alkalmazás állapota megváltozik: active, inactive, background. A képernyőn töltött idő nyomon követéséhez használja az onAppear+onDisappeart, a globális állapot mentéséhez a scenePhase-t.
Az ok — gyors lapozás a lapok között vagy ugyanazon képernyő ismételt push/pop-ja. A SwiftUI létrehozhat egy új View-példányt, eltávolíthatja a régit, majd újra létrehozhatja — minden alkalommal onDisappeart és onAppeart kiváltva. Ellenőrizze, hogy használ-e .id()-t, .equatable()-t, vagy hogy újra létrehozza-e a View-t a szülő body-jában.
Igen, az .onDisappear teljes mértékben támogatott macOS-en (10.15+) ugyanazzal a viselkedéssel: ablak bezárásakor, split view panel eltávolításakor vagy modális ablak elutasításakor hívódik. macOS-en az onDisappear az ablak elrejtésekor (hide) is meghívódik, nem csak bezáráskor, ami fontos a macOS alkalmazások esetében.
Mentse el a URLSessionTask-re való hivatkozást @State-be, és hívja meg a task.cancel()-t az onDisappearben. Alternatívaként használja a .task módosítót, amely automatikusan törli az async műveletet a View eltűnésekor. A .task előnyben részesítendő minden async művelethez, beleértve a URLSession-t is.
Ö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