viewWillDisappear är en metod i UIViewController som UIKit anropar omedelbart innan skärmen börjar försvinna från användarens display. Enligt Apple Developer Documentation tar denna metod emot parametern animated och utlöses vid push, pop, present, dismiss och växling av flikar. viewWillDisappear är den främsta platsen för att spara tillstånd och korrekt rensa resurser.
Huvudpunkter
viewWillDisappear är en metod i UIViewController som UIKit anropar omedelbart innan kontrollerns View börjar försvinna från skärmen. I detta ögonblick är skärmen fortfarande synlig för användaren, men övergången har redan påbörjats: NavigationController har startat push/pop-animeringen, det modala fönstret har börjat stängas eller TabBar har börjat växla till en annan flik. Utvecklaren åsidosätter denna metod för att utföra operationer som kräver att skärmen fortfarande är tillgänglig, men som redan förbereder sig för att döljas.
Till skillnad från viewDidDisappear som utlöses efter att skärmen dolts, ger viewWillDisappear sista chansen att spara data och frigöra resurser medan användaren fortfarande ser gränssnittet. Detta är avgörande för UX — att spara ett utkast eller stoppa en timer måste ske innan användaren växlar till en annan skärm.
Metoden tar emot parametern animated, som indikerar om försvinnandet sker med animering. Värdet true innebär att UIKit utför övergången med animering, false — skärmen försvinner omedelbart, till exempel vid dismiss utan animering eller vid programmeringsmässig borttagning från hierarkin.
viewWillDisappear anropas i alla scenarier när den aktuella skärmen slutar vara aktiv. Låt oss titta på de huvudsakliga fallen som är specifika för iOS-utveckling.
När UINavigationController utför en push av en ny kontroller, anropas viewWillDisappear på den aktuella kontrollern i början av övergångsanimeringen. I detta ögonblick är den aktuella skärmen fortfarande synlig under den nya kontrollern som glider ovanpå den. Detta är standardscenariot där viewWillDisappear utlöses med animated = true.
När användaren trycker på tillbakaknappen eller utför en interaktiv svepgest bakåt, anropas viewWillDisappear på den aktuella kontrollern. Vid en interaktiv gest kan detta anrop avbrytas om användaren ångrar sig och återställer skärmen på plats. Detta är en viktig egenskap som måste beaktas vid design av tillståndssparande.
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
saveDraftData()
NotificationCenter.default.removeObserver(self)
}
När ett modalt fönster stängs anropas viewWillDisappear på kontrollern som stängs i början av dismiss-animeringen. I detta ögonblick kan resultat skickas tillbaka via delegat eller closure, eftersom kontrollern som presenterade det modala fönstret ännu inte har fått kontrollen.
UITabBarController anropar viewWillDisappear på kontrollern för den lämnade fliken omedelbart efter att användaren tryckt på en annan flik. Om det på den aktuella fliken finns aktiva processer — mediauppspelning, filnedladdning, timer — pausas eller stoppas de här.
viewWillDisappear löser konkreta uppgifter inom resurs- och tillståndshantering. Låt oss titta på nyckelscenarier med kodexempel.
Den viktigaste uppgiften för viewWillDisappear — att spara data som användaren har angett eller ändrat på den aktuella skärmen. Meddelandeutkast, redigerade formulärfält, valda inställningar — allt detta måste sparas innan skärmen försvinner. Använd Core Data, UserDefaults eller fil lagring för beständighet.
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
guard hasUnsavedChanges else { return }
draftStorage.save(currentDraft)
}
NotificationCenter, KVO och Combine-publishers som du prenumererat på i viewWillAppear eller viewDidLoad måste avbrytas i viewWillDisappear. Om du inte gör detta kommer notifikationer att komma till den dolda skärmen, vilket orsakar UI-uppdateringar som användaren inte ser, eller värre — krascher på grund av referenser till redan frigjorda objekt.
UIView-animationer startade i viewDidAppear och timers som fungerar via Timer eller DispatchSource måste stoppas i viewWillDisappear. Fortsatta animationer på en dold skärm förbrukar GPU och batteri utan någon nytta för användaren. Stoppa dem explicit genom att anropa invalidate på timers och removeAllAnimations på lager.
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
countdownTimer?.invalidate()
countdownTimer = nil
loadingIndicator.layer.removeAllAnimations()
}
Om kontrollern öppnades för att få ett resultat — val av element, textinmatning, bekräftelse av åtgärd — är viewWillDisappear det sista ögonblicket då den ursprungliga kontrollern fortfarande finns i stacken och kan ta emot data. Anropa delegaten eller closure innan deinit anropas.
Tillförlitligt sparande av skärmens tillstånd är en av de svåraste uppgifterna inom iOS-utveckling. ViewWillDisappear är en viktig, men inte den enda delen av strategin. Låt oss titta på en omfattande metod.
Nivå 1 — spara i viewWillDisappear. Snabb sparning av lätta data som måste vara tillgängliga omedelbart efter återkomst. Lämplig för UI-tillstånd: scrollposition, valt segment, text i inmatningsfält. Problem: vid en avbruten interaktiv pop-gest sker sparningen även om användaren stannade kvar på skärmen — data skrivs över i onödan.
Nivå 2 — spara i viewDidDisappear. Duplicerar sparningen från första nivån, men utlöses först efter att skärmen garanterat dolts. Detta är en försäkring mot avbrutna gester. Men om du i viewWillDisappear redan har avprenumererat från notifikationer, kan viewDidDisappear sakna tillgång till vissa data.
Nivå 3 — spara via applikationsnotifikationer. UIApplication.willResignActiveNotification och UIApplication.didEnterBackgroundNotification fångar upp minimering av appen. Om användaren minimerade appen kanske viewWillDisappear inte anropades — men sparning via dessa notifikationer garanterar dataintegriteten vid sessionens slut.
| Nivå | Metod/Notifikation | Tillförlitlighet | Användning |
|---|---|---|---|
| 1 | viewWillDisappear | Hög | UI-tillstånd, utkast |
| 2 | viewDidDisappear | Mycket hög | Kritiska data |
| 3 | willResignActive | Maximal | Vid minimering |
Rekommendation: använd en kombination av alla tre nivåer för kritisk användardata. För icke-kritiskt tillstånd räcker första nivån. Det är viktigt att inte skriva över samma data flera gånger — använd en dirty-flagga som indikerar att data har ändrats sedan senaste sparningen.
Särskild uppmärksamhet bör ägnas åt strategin för CRUD-skärmar, där användaren anger data. På sådana skärmar rekommenderas inte att spara varje tangenttryckning i viewWillDisappear — det är överflödigt. Använd autosparning med fördröjning (debounce) via Timer och tillämpa viewWillDisappear endast för slutgiltig forcerad sparning om det finns osparade ändringar. En sådan metod balanserar mellan prestanda och datasäkerhet.
För applikationer med Core Data är en extra åtgärd att anropa saveContext i viewWillDisappear endast när det finns faktiska ändringar i managed object context. Kontroll av context.hasChanges före sparning förhindrar onödiga skrivningar till persistent store och förlänger enhetens batteritid. Kombinera denna kontroll med global sparning i applicationDidEnterBackground.
Felaktig användning av viewWillDisappear kan leda till dataförlust, minnesläckor och instabilt beteende i applikationen. Låt oss titta på vanliga misstag hos iOS-utvecklare.
Första misstaget — att bara spara data i viewWillDisappear. Som diskuterats ovan, vid en interaktiv pop-gest anropas metoden även om skärmen inte försvinner. Om sparningen har bieffekter — skicka data till servern, ändra tillstånd — kan detta leda till falska utlösningar. Lägg till kontroll av isBeingDismissed eller isMovingFromParent.
Andra misstaget — att inte avprenumerera från NotificationCenter. Detta är en av de vanligaste minnesläckorna i iOS. Om du prenumererade i viewWillAppear på UIResponder.keyboardWillShowNotification men inte avprenumererade i viewWillDisappear, fortsätter closuren att anropas. Vid deinit av kontrollern kommer closuren att referera till ett frigjort objekt — krasch av applikationen är garanterad.
Tredje misstaget — att utföra tunga synkrona operationer. Att spara en stor mängd data, skriva till Core Data eller filsystemet i viewWillDisappear blockerar main thread. Om operationen varar längre än övergångsanimeringen, pausar UIKit tråden och gränssnittet fryser. Flytta tunga sparningar till bakgrundsköer.
Fjärde misstaget — att glömma anropa super. Att inte anropa super.viewWillDisappear kan störa funktionen hos UINavigationController och UITabBarController, som använder denna metod för sina interna tillstånd. Anropa alltid super först eller sist, enligt Apples dokumentation.
Detta problem förvärras på iOS med aktiv multitasking och växling mellan applikationer. Femte misstaget — att använda DispatchQueue.main.async efter sparning i viewWillDisappear. Om du asynkront skickar ett block till huvudkön efter att ha anropat super.viewWillDisappear, finns det ingen garanti för att kontrollern fortfarande finns vid blockets exekvering. Använd alltid svaga referenser [weak self] inuti closures för att förhindra referens till frigjort minne och förhindra krascher i applikationen.
Vanliga frågor
viewWillDisappear anropas i början av försvinnandet, när skärmen fortfarande är synlig. viewDidDisappear — efter att skärmen är helt dold och animeringen är klar.
Använd viewDidDisappear för bekräftelse av sparning eller kontrollera egenskaperna isMovingFromParent och isBeingDismissed inuti viewWillDisappear för att avgöra om skärmen verkligen kommer att försvinna.
Ja, absolut, om du använder block eller selektorer med self. ARC hanterar inte prenumerationer på NotificationCenter. I iOS 9+ för block använd en svag referens och avprenumerera i viewWillDisappear.
Inte alls — force quit anropar inte Lifecycle-metoder. För garanterad sparning vid avslut av applikationen använd UIApplication.willTerminateNotification eller spara data i realtid när de ändras.
Ja, vid interaktiv pop-gest anropar UIKit viewWillDisappear omedelbart efter gestens start. Om användaren avbryter gesten förblir skärmen synlig, men metoden har redan utlösts. Kontrollera alltid isMovingFromParent.
Sammanfattning
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.
Läs också