.onDisappear: funktionsprincip och tillämpning i SwiftUI

Författare: IT Sectr Publicerad: 2026-06-26 Lästid: 10 min

.onDisappear — en SwiftUI-modifierare som utför en closure när en View tas bort från gränssnittshierarkin. Anropet sker vid stängning av skärmen, byte av flik, dismiss av modalt fönster eller scrollning av ett element utanför synligt område. Enligt Apple Developer Documentation (2026) garanterar onDisappear inte anrop i scenarier med nödavslutning eller när applikationen förstörs av system-watchdog. Läs mer om SwiftUI i materialet om SwiftUI.

Huvudpunkter

  • .onDisappear — SwiftUI-modifierare för att utföra kod när en View försvinner.
  • Symmetri — onDisappear är i par med onAppear och anropas i omvänd ordning.
  • Rensning av resurser — huvudsakligt scenario: annullering av timers, stängning av anslutningar, sparande av tillstånd.
  • Analys — via onDisappear skickas händelser screen close, dwell time, session end.
  • Ingen garanti — onDisappear anropas inte vid nödavslutning av applikationen.

Vad är .onDisappear?

.onDisappear — en View-modifierare i SwiftUI som accepterar en Void-closure och utför den när View tas bort från hierarkin. Tillsammans med .onAppear bildar den en fullständig livscykel för skärmen: uppträdande — arbete — försvinnande. Apple introducerade onDisappear tillsammans med lanseringen av SwiftUI i iOS 13 som en analog till viewDidDisappear från UIKit.

Syntaxmässigt är .onDisappear identisk med onAppear: modifierar vilken View som helst och kopplar en closure som anropas av SwiftUI-komponenten när vyn tas bort. Till skillnad från UIKit där viewDidDisappear aktiveras först efter att övergångsanimationen slutförts, kan onDisappear i SwiftUI anropas innan animationen är klar — i det ögonblick som View markeras för borttagning.

Syntax för onDisappear

Grundläggande syntax för onDisappear är lika koncis som onAppear. Modifieraren accepterar inga ytterligare parametrar — endast closuren som utförs synkront i huvudtråden.

swift
struct DetailView: View {
    var body: some View {
        Text("Detaljskärm")
            .onDisappear {
                print("DetailView försvann från skärmen")
            }
    }
}

Hur fungerar .onDisappear

Anropsmekanism för onDisappear är motsatsen till onAppear: först får underordnade element onDisappear, sedan föräldern. Denna child-first-regel garanterar att resurser för underordnade element frigörs innan förälderns resurser frigörs. Om ett underordnat element är beroende av förälderns data måste det kunna avslutas korrekt utan förälderns kontext.

SwiftUI anropar onDisappear i det ögonblick som View utesluts från renderingsgrafen. Utlösaren kan vara: pop från NavigationStack, byte av TabView, dismiss av modalt fönster (sheet/fullScreenCover), ändring av villkorligt visad View (if/switch). I List och ScrollView anropas onDisappear när en cell scrollas utanför prefetch-bufferten.

Anropsordning child-first

Child-first-ordning innebär att om det finns tre underordnade Views i en VStack, kommer onDisappear att anropas först för varje barn i omvänd ordning, sedan för föräldern. Detta är kritiskt för korrekt rensning: underordnade timers annulleras innan förälderns ViewModel frigör delade resurser.

swift
struct ParentView: View {
    var body: some View {
        VStack {
            ChildView(id: "A")
            ChildView(id: "B")
        }
        .onDisappear {
            print("Parent onDisappear — sist")
        }
    }
}

struct ChildView: View {
    let id: String
    var body: some View {
        Text("Barn \(id)")
            .onDisappear {
                print("Barn \(id) onDisappear")
            }
    }
}

Konsoloutput: Child B onDisappear, Child A onDisappear, Parent onDisappear — sist. Omvänd ordning jämfört med onAppear garanterar en korrekt frigörandekedja.

När anropas .onDisappear

Anropscenarier för onDisappear beror på containertypen. I NavigationStack utlöses onDisappear vid pop-to-root, vanlig pop-back eller borttagning av skärm genom svepgest (interactivePopGestureRecognizer). I TabView utlöser byte av flik onDisappear för den dolda och onAppear för den visade — båda modifierarna utlöses nästan samtidigt.

I Sheet och fullScreenCover anropas onDisappear vid programmatisk dismiss (via @Environment(\.dismiss)) eller svepgest nedåt. En viktig egenskap: om sheet har öppnats men användaren har bytt app, anropas onDisappear INTE förrän själva stängningen.

ScenarioonDisappear anropasAnmärkning
Pop i NavigationStackJaOmedelbart efter animation
Flikbyte i TabViewJaAktuell flik
Dismiss av sheetJaInnan animation slutförs
Scroll i ListJaCell utanför prefetch-zon
Minimering av appNejIngen garanti för anrop
Crash/watchdog killNejAnropas inte

Exempel på .onDisappear

Huvudscenarier för onDisappear — rensning av resurser, sparande av tillstånd och spårning. Till skillnad från onAppear utförs onDisappear-uppgifter vid utgång och kräver ingen kontroll för dubbelarbete eftersom View försvinner en gång.

Spara tillstånd och annullera timers

Spara tillstånd i onDisappear är särskilt användbart för formulär där data måste sparas när man lämnar skärmen. Timers och Combine-prenumerationer annulleras i onDisappear för att undvika minnesläckor vid återgång till skärmen.

swift
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")
    }
}

Annullering av timer i onDisappear förhindrar att kod körs efter att skärmen stängts. Utan annullering kan timern försöka uppdatera ett @State som inte längre tillhör den aktuella View, vilket orsakar en runtime-varning.

Spårning av tid på skärmen

Vistelsetid på skärmen — ett klassiskt spårningscenario. Vi registrerar tiden i onAppear, beräknar skillnaden i onDisappear och skickar en analytisk händelse med sessionens varaktighet.

swift
struct TrackedView: View {
    @State private var appearTime: Date?
    
    var body: some View {
        Text("Spårad Skärm")
            .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)
                    ])
                }
            }
    }
}

.onDisappear vs .onAppear — skillnader

Den viktigaste skillnaden mellan onDisappear och onAppear — anropsordningen och aktiveringsgarantierna. onAppear anropas när View läggs till i hierarkin och har egenskapen att återanropas vid återskapande. onDisappear anropas vid borttagning och fungerar garanterat endast vid normal stängning, men inte i nödsituationer.

Enligt WWDC 2024 rekommenderar Apple att onDisappear betraktas som en renspunkt, inte som en datalagringspunkt. Kritisk viktig data (betalningar, registreringar) bör sparas i realtid, inte i ögonblicket när View försvinner, eftersom onDisappear inte garanterar anrop när appen minimeras.

Egenskap.onAppear.onDisappear
AnropstillfälleView läggs till i hierarkiView tas bort från hierarki
OrdningParent-firstChild-first
GarantiHögInte vid nödavslutning
HuvuduppgiftInitieringRensning
ÅteranropVid återskapande av ViewEn gång per försvinnande

Rekommendation: använd onDisappear endast för icke-kritisk rensning och spårning. För att spara data, använd scenePhase eller applicationWillTerminate-meddelanden i AppDelegate.

Typiska användningsscenarier

Scenario 1: YouTube-liknande laddning. På videodetaljskärmen sparar onDisappear uppspelningspositionen i UserDefaults. Vid återöppning återställer onAppear positionen från UserDefaults, vilket ger en kontinuerlig tittarupplevelse.

Scenario 2: annullering av Combine-prenumeration. Om ViewModel använder Combine-publishers, annullerar onDisappear prenumerationen via cancellable?.cancel(). Detta förhindrar UI-uppdateringar efter att skärmen lämnats, vilket är särskilt viktigt för listor med paginering och sökfrågor.

Scenario 3: stängning av WebSocket. I appar med realtidsanslutningar (meddelandetjänster, kursflöden) stänger onDisappear WebSocket-anslutningen för att spara batteri och trafik. Återöppning sker i onAppear vid återgång till skärmen.

Stängning av WebSocket i onDisappear

WebSocket — en typisk resurs som bör stängas när man lämnar skärmen. I exemplet nedan kopplar onDisappear bort socketen och onAppear återansluter den, vilket ger betydande trafikbesparingar för appar med flera skärmar.

swift
struct ChatView: View {
    @StateObject private var socket = WebSocketManager()
    
    var body: some View {
        ChatListView(messages: socket.messages)
            .onAppear {
                socket.connect()
            }
            .onDisappear {
                socket.disconnect()
            }
    }
}

Viktigt: vid växling mellan flikar i TabView utlöses onDisappear för den aktuella fliken och onAppear för nästa flik nästan samtidigt. För WebSocket kan detta leda till en disconnect-connect-cykel som skapar extra belastning. Lösning — använd en fördröjning eller kontrollera om socketen behövs på nästa skärm.

Vanliga frågor

Kan .onDisappear utebli?

Ja, .onDisappear garanterar inte anrop vid nödavslutning av appen (crash, watchdog kill), minimering av appen utan att stänga skärmen eller systemscenario där appen förstörs i bakgrunden. För kritisk viktig data, använd scenePhase eller applicationWillTerminate.

Hur skiljer man .onDisappear från .scenePhase?

.onDisappear utlöses när View tas bort från hierarkin — en lokal callback för en specifik skärm. .scenePhase (via @Environment(\.scenePhase)) utlöses när hela appens tillstånd ändras: active, inactive, background. För spårning av tid på skärmen, använd onAppear+onDisappear, för lagring av globalt tillstånd — scenePhase.

Varför anropas .onDisappear flera gånger i rad?

Orsaken — snabb växling mellan flikar eller upprepad push/pop av samma skärm. SwiftUI kan skapa en ny View-instans, ta bort den gamla, skapa igen — varje gång utlöses onDisappear och onAppear. Kontrollera om du använder .id(), .equatable() eller om du återskapar View i förälderns body.

Fungerar .onDisappear i SwiftUI på macOS?

Ja, .onDisappear stöds fullt ut på macOS (10.15+) med samma beteende: anropas vid stängning av fönster, borttagning av split view-panel eller dismiss av modalt fönster. På macOS anropas onDisappear även vid döljande av fönster (hide), inte bara vid stängning, vilket är viktigt för macOS-applikationer.

Hur annullerar man URLSessionTask i .onDisappear?

Spara referensen till URLSessionTask i @State och anropa task.cancel() i onDisappear. Alternativt, använd .task-modifieraren som automatiskt annullerar async-operationen när View försvinner. .task är att föredra för alla async-operationer, inklusive URLSession.

Sammanfattning

  • .onDisappear — parmodifierare till onAppear för rensning av resurser och spårning när View försvinner.
  • Child-first-ordning — underordnade Views får onDisappear tidigare än föräldern för korrekt frigörandekedja.
  • Ingen anropsgaranti — vid crash, minimering eller systemavslutning kan onDisappear fungera.
  • Huvudscenarier — annullering av timers, stängning av WebSocket, sparande av tillstånd, spårning av varaktighet.
  • Analys — onDisappear skickar screen_close-händelser med beräkning av dwell time via Date().timeIntervalSince.
  • För async-operationer — använd .task istället för onDisappear med Task {}, eftersom .task automatiskt annullerar förfrågningar.

Vi utvecklar en mobil applikation nyckelfärdigt

IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.

Diskutera projektet

Läs också