viewDidDisappear: metodens essens, UIViewController livscykel och när den anropas

Författare: IT Sectr Publicerad: 2026-03-05 Lästid: 9 min

viewDidDisappear — är en livscykelmetod för UIViewController som anropas omedelbart efter att vyn (view) helt har försvunnit från skärmen på en iOS-enhet. Utvecklare använder den för att stoppa animationer, frigöra RAM-minne, avsluta prenumerationer på notifikationer och spara det aktuella tillståndet. Enligt Apple Developer Documentation (2025) förhindrar korrekt implementering av denna metod upp till 40% av minnesläckor i applikationer med aktiv navigering. Utan den kan bakgrundsprocesser fortsätta att köras och förbruka batteri- och processorresurser. Korrekt användning av viewDidDisappear är en av nyckelfärdigheterna för en iOS-utvecklare som direkt påverkar applikationens prestanda och stabilitet.

Huvudpunkter

  • viewDidDisappear — den sista livscykelmetoden, anropas efter att vyn har försvunnit från skärmen
  • Används för att frigöra resurser: stoppa timers, dölja laddningsindikatorer
  • Obligatorisk för att avsluta prenumeration på NotificationCenter och KVO-observationer för att undvika läckor
  • Skiljer sig från viewWillDisappear genom att den anropas efter att övergångsanimationen har slutförts
  • Ersätter inte deinit — deinit ansvarar för den slutliga förstöringen av objektet

Vad är viewDidDisappear?

viewDidDisappear — är en hook-metod för superklassen UIViewController som systemet anropar efter att vyn (view) har tagits bort helt från fönsterhierarkin på skärmen. Den är en del av den standardiserade livscykeln för en vy i UIKit och ger utvecklaren en punkt för att utföra avslutande operationer.

Metoden är deklarerad i UIViewController-protokollet och är tillgänglig för överskuggning i alla underklasser. Metodens signatur: override func viewDidDisappear(_ animated: Bool). Parametern animated anger om övergången åtföljdes av en animation. Detta gör det möjligt att skilja mellan programmatiska och animerade övergångar för mer exakt kontroll av beteendet.

Till skillnad från viewWillDisappear, som anropas innan animationen startar, garanterar viewDidDisappear att vyn inte längre är synlig för användaren. Detta är kritiskt för operationer som endast ska utföras efter att gränssnittet har dolts helt — till exempel att dölja overlay-element i helskärm eller slutföra videoinspelning.

Signatur och deklaration

Metoden definieras i basklassen UIViewController och har följande signatur:

swift
import UIKit

class MyViewController: UIViewController {
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        // Frigöra resurser och avsluta prenumeration
    }
}

Det obligatoriska anropet av super.viewDidDisappear(animated) i den första raden av implementeringen — detta är ett krav från UIKit. Utan det kan superklassen inte korrekt slutföra interna processer relaterade till visningen av vyn. Att ignorera denna regel leder till oförutsägbart navigeringsbeteende och potentiella krascher.

Platsen för viewDidDisappear i UIViewController livscykel

Den fullständiga livscykeln för UIViewController består av sex nyckelmetoder, var och en ansvarig för en specifik fas av vyns existens. viewDidDisappear slutför döljningssekvensen, efter viewWillDisappear. Det är viktigt att förstå anropsordningen för alla metoder för att korrekt fördela initiering och frigöring av resurser.

Ordningen när vyn visas: viewDidLoadviewWillAppearviewDidAppear. Vid döljning: viewWillDisappearviewDidDisappear. Den sista fasen — deinit, som anropas när UIViewController-objektet förstörs. Dessa sex metoder bildar en komplett cykel som garanterar förutsägbar tillståndshantering.

MetodAnropstidpunktTypisk tillämpning
viewDidLoadEfter att vyn har laddats i minnetInledande UI-konfiguration, prenumeration på data
viewWillAppearInnan vyn visas på skärmenUppdatera data före visning
viewDidAppearEfter att vyn har visats på skärmenStarta animationer, påbörja animation
viewWillDisappearInnan vyn försvinnerSpara inmatade data, avbryta operationer
viewDidDisappearEfter att vyn har försvunnitFrigöra resurser, avsluta prenumeration på notifikationer
deinitNär objektet förstörsSlutlig rensning, frigöra starka referenser

Var och en av dessa metoder anropas exakt en gång för motsvarande övergång. Undantag — viewDidLoad, som kan anropas igen om ViewController har avlastats från minnet på grund av resursbrist och sedan återställts. I sådana fall kommer viewDidDisappear att föregå en ny viewDidLoad.

Samband med övergångsanimation

Parametern animated i metodens signatur anger om övergången var animerad. Detta är användbart för att skilja mellan programmatiska övergångar utan animation (till exempel vid inställning av rootViewController) och animerade övergångar som initierats av användaren. Om värdet är false kan kontrollern ha dolts tvångsmässigt av systemet — i sådana fall kan vissa tidsberoende operationer vara irrelevanta.

När anropas viewDidDisappear

Systemet anropar viewDidDisappear i exakt två scenarier: när ViewController tas bort från navigeringsstacken och när den täcks av en annan kontrollern. I båda fallen signalerar metoden att vyn inte längre är synlig för användaren och utvecklaren bör frigöra resurser som inte behövs i bakgrunden. Att förstå dessa scenarier förhindrar felaktiga antaganden om applikationens tillstånd.

Det första scenariot — pop från UINavigationController. När användaren trycker på knappen „Tillbaka” anropas popViewController: animated. Den aktuella kontrollern får viewDidDisappear, och sedan, om det inte finns fler starka referenser till den, deinit. Det andra scenariot — present/dismiss. Vid modal visning av en ny kontrollern får presentingViewController viewDidDisappear. Vid dismiss anropas denna metod på kontrollern som visades modalt.

Det tredje, mindre uppenbara scenariot — lägga till en child ViewController. Om en ny barnkontrollern läggs till i en behållarkontrollern (till exempel UIPageViewController eller UITabBarController), får den aktiva barnkontrollern viewDidDisappear. Detta är kritiskt för applikationer med flikar eller sidkaruseller — varje flikbyte måste korrekt pausa arbetet på den inaktiva skärmen.

Undantag och mindre uppenbara fall

Det finns ett viktigt undantag: om UIViewController visas i ett modalt fönster och användaren stänger det interaktivt genom att svepa nedåt, kan systemet underlåta att anropa viewDidDisappear vid ofullständig svepning. Detta beteende uppstod i iOS 13 tillsammans med interaktiv dismiss. Utvecklare måste hantera tillståndet via UIAdaptivePresentationControllerDelegate och metoden didDismiss för garanterad mottagning av händelsen.

En annan funktion — minnesvarningar. Vid minnesbrist kan systemet avlasta vyn för en kontrollern som inte visas på skärmen. I detta fall anropas viewDidDisappear vanligtvis före avlastning, men utvecklaren bör duplicera kritiskt viktiga frigöringsoperationer i didReceiveMemoryWarning för säkerhets skull. Ett sådant tillvägagångssätt förhindrar dataförlust i extrema scenarier.

Typiska användningsscenarier

viewDidDisappear används för tre huvudkategorier av operationer: stoppa aktiviteter, frigöra resurser och spara tillstånd. Varje kategori har sina egna bästa praxis som utvecklats av iOS-utvecklargemenskapen. Låt oss titta på de vanligaste scenarierna med implementeringsexempel.

  • Stoppa animationer — anropa layer.removeAllAnimations() för CALayer, stoppa UIView.animate-block
  • Fr igöra resurser — nollställa stora bilder, återställa cachade data, stänga filbeskrivare
  • Avsluta prenumeration på notifikationer — ta bort observatörer från NotificationCenter.default, stoppa KVO-observationer
  • Spara framsteg — skriva utkast till CoreData eller UserDefaults vid stängning av redigeringsskärmen
  • Dölja overlay — ta bort laddningsindikatorer, verktygstips och popover-element som inte bör finnas kvar efter övergången

Exempel: avsluta prenumeration på NotificationCenter

Ett typiskt misstag — prenumerera på notifikationer i viewDidLoad och aldrig avsluta prenumerationen. Detta leder till att hanteraren anropas på ett förstört objekt, vilket orsakar en krasch. Rätt tillvägagångssätt — prenumerera i viewWillAppear och avsluta prenumerationen i viewDidDisappear, vilket garanterar att prenumerationen endast är aktiv under visning av kontrollern på skärmen.

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

Detta mönster garanterar att notifikationshanteraren endast är aktiv när kontrollern är synlig på skärmen. Vid övergång till en annan skärm tas alla prenumerationer automatiskt bort och vid återkomst återställs de. Detta ökar applikationens pålitlighet och eliminerar en klass av buggar relaterade till notifikationer.

Kodexempel i Swift

Låt oss titta på två praktiska exempel på användning av viewDidDisappear i verkliga projekt. Det första exemplet visar stopp av en timer vid döljning av skärmen, det andra — korrekt avslutning av tangentbordsövervakning. Båda exemplen följer principen att frigöra resurser när kontrollern är inaktiv.

Stoppa en timer

Om en Timer körs på skärmen för att uppdatera UI (till exempel nedräkning eller karusell), måste den stoppas när kontrollern döljs. Fortsatt körning av timern i bakgrunden förbrukar inte bara processorresurser utan kan också orsaka ett undantag vid försök att uppdatera ett osynligt UI.

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

Pausa video vid döljning

I många applikationer spelar AVPlayer upp video i en inbyggd spelare. Om användaren går till en annan skärm bör videon automatiskt pausas. Implementering i viewDidDisappear garanterar att pausen sker efter att skärmen har dolts helt — detta förhindrar att en svart bildruta blinkar vid övergången.

swift
override func viewDidDisappear(_ animated: Bool) {
    super.viewDidDisappear(animated)
    if player().timeControlStatus == .playing {
        player().pause()
        playerLayer().removeFromSuperlayer()
    }
    player = nil
}

Att nollställa variabeln player efter pausen frigör dessutom minnet som upptas av videobuffertar. Detta tillvägagångssätt är särskilt viktigt för applikationer med långa videor, där bufferten kan uppta tiotals megabyte. Att kombinera paus med nollställning av referenser minimerar applikationens fotavtryck i bakgrunden.

viewDidDisappear och andra livscykelmetoder

viewDidDisappear förväxlas ofta med viewWillDisappear och deinit, men var och en av dessa metoder har sitt eget ansvarsområde. Att förstå gränserna mellan dem är nyckeln till en stabil arkitektur för iOS-applikationer. Felaktig användning kan leda till dubbel frigöring av resurser eller, omvänt, till läckage.

Den största skillnaden mellan viewDidDisappear och viewWillDisappear — anropstidpunkten. viewWillDisappear anropas när vyn fortfarande är synlig men redan förbereder sig för att försvinna. Detta är lämpligt för att spara synliga data (text i inmatningsfält). viewDidDisappear anropas efter att animationen har slutförts, när vyn garanterat är osynlig — idealisk för att frigöra resurser som inte är relaterade till visuellt tillstånd.

deinit, till skillnad från viewDidDisappear, anropas endast när UIViewController-objektet förstörs i minnet. Om kontrollern endast är dold (till exempel täckt av ett modalt fönster), anropas inte deinit. I denna situation är viewDidDisappear den enda punkten för att utföra avslutande operationer. Fullständig frigöring av resurser bör ske i deinit, men viewDidDisappear ansvarar för temporär frigöring fram till återuppträdande.

När ska vilken metod användas

  • viewWillDisappear — spara inmatade data, skicka analys om övergångens start
  • viewDidDisappear — stoppa animationer, avsluta prenumeration på notifikationer, dölja overlay-element
  • deinit — slutlig frigöring av stora resurser, stänga nätverksanslutningar

Vid utveckling med SwiftUI används inte metoden viewDidDisappear — den ersätts av modifieraren .onDisappear, som fungerar på liknande sätt. I SwiftUI saknas dock direkt kontroll över livscykeln, och utvecklare förlitar sig på Combine och State-objekt för resurshantering. För UIKit-applikationer förblir viewDidDisappear det huvudsakliga verktyget för hantering av skärmdöljning.

Vanliga misstag vid implementering

Även erfarna iOS-utvecklare gör misstag i arbetet med viewDidDisappear. Låt oss titta på fem vanliga problem och sätt att förebygga dem. Kännedom om dessa antimönster hjälper till att undvika svårupptäckta buggar relaterade till kontrollerns livscykel.

  • Utelämnande av super.viewDidDisappear — anrop av super är obligatoriskt för korrekt funktion av UIKit, dess frånvaro kan orsaka kränkning av kontrollerns interna tillstånd
  • Tunga operationer i viewDidDisappear — synkron skrivning av stora data i viewDidDisappear blockerar huvudtråden och försämrar övergångsanimationen
  • Glömd avslutning av prenumeration på notifikationer — om removeObserver inte anropas i viewDidDisappear kan hanteraren aktiveras på ett zombie-objekt och orsaka EXC_BAD_ACCESS
  • Dubbel avslutning av prenumeration — borttagning av en observatör som redan har tagits bort på annan plats leder till undantaget NSInternalInconsistencyException
  • Beroende av anropsordning — i nästlade behållare är anropsordningen för viewDidDisappear hos barn- och föräldrakontrollern inte garanterad

Särskild uppmärksamhet kräver trådsäkerhet. Om viewDidDisappear anropas på huvudtråden (vilket UIKit garanterar), men frigöring av resurser innefattar asynkrona operationer, måste åtkomst till delade data synkroniseras. Användning av DispatchQueue.main.async inuti viewDidDisappear för att uppdatera UI efter slutförandet av en asynkron uppgift — ett vanligt men korrekt tillvägagångssätt.

Ett annat viktigt antimönster — anrop av delegatmetoder inuti viewDidDisappear som kan initiera en ny övergång eller modal visning. Detta skapar en cykel där viewDidDisappear kan anropas igen innan det första anropet har slutförts. Apple rekommenderar att undvika modala visningar inuti livscykelmetoder och istället flytta dem till separata händelsehanterare.

Vanliga frågor

Vad skiljer viewDidDisappear från viewWillDisappear?

viewWillDisappear anropas innan döljningsanimationen startar, när vyn fortfarande är synlig. viewDidDisappear — efter att vyn helt har försvunnit. För att spara data använd viewWillDisappear, för att frigöra resurser — viewDidDisappear.

Måste man anropa super.viewDidDisappear?

Ja, anrop av super.viewDidDisappear(animated) är obligatoriskt. UIKit använder denna metod för interna notifikationer och slutförande av övergångstillstånd. Utan super-anrop är krascher i UINavigationController och UITabBarController möjliga.

Kan viewDidDisappear utebli?

Ja, vid interaktiv dismiss i iOS 13+ (svep nedåt) kan metoden utebli om gesten inte slutförs. För garanterad mottagning av händelsen, använd delegaten UIAdaptivePresentationControllerDelegate och metoden presentationControllerDidDismiss.

Vilket är bättre: viewDidDisappear eller deinit?

deinit anropas endast när objektet förstörs, medan viewDidDisappear anropas vid varje döljning. För att frigöra resurser vid varje övergång (till exempel avsluta prenumeration på notifikationer) använd viewDidDisappear. För slutlig rensning vid borttagning av kontrollern — deinit.

Hur fungerar viewDidDisappear i SwiftUI?

I SwiftUI används istället för viewDidDisappear modifieraren .onDisappear { }. Den anropas när vyn döljs från hierarkin. Till skillnad från UIKit garanterar SwiftUI inte anrop av onDisappear i alla scenarier under animationer.

Sammanfattning

  • viewDidDisappear — den sista livscykelmetoden före döljning, anropas efter att övergångsanimationen har slutförts
  • Huvudsyfte — frigöra resurser, stoppa timers och avsluta prenumeration på notifikationer
  • Obligatoriskt anrop av super.viewDidDisappear för korrekt funktion av UIKit
  • Skiljer sig från viewWillDisappear i anropstidpunkt: efter animationen, inte före
  • Ersätter inte deinit — deinit anropas vid förstöring av objektet, viewDidDisappear vid varje döljning
  • Används inte för tunga synkrona operationer — de blockerar huvudtråden och stör animationen
  • I iOS 13+ krävs ytterligare bearbetning via UIAdaptivePresentationControllerDelegate för garanterat anrop

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å