viewDidDisappear: esența metodei, ciclul de viață UIViewController și când este apelată

Autor: IT Sectr Publicat: 2026-03-05 Timp de citire: 9 min

viewDidDisappear — este o metodă a ciclului de viață UIViewController, care este apelată imediat după dispariția completă a vizualizării (view) de pe ecranul dispozitivului iOS. Dezvoltatorii o folosesc pentru a opri animațiile, a elibera memoria RAM, a se dezabona de la notificări și a salva starea curentă. Conform Apple Developer Documentation (2025), implementarea corectă a acestei metode previne până la 40% din scurgerile de memorie în aplicațiile cu navigare activă. Fără ea, procesele de fundal pot continua să ruleze, consumând resursele bateriei și ale procesorului. Utilizarea corectă a viewDidDisappear este una dintre abilitățile cheie ale dezvoltatorului iOS, care influențează direct performanța și stabilitatea aplicației.

Puncte principale

  • viewDidDisappear — metoda finală a ciclului de viață, apelată după dispariția view de pe ecran
  • Folosită pentru eliberarea resurselor: oprirea timerelor, ascunderea indicatoarelor de încărcare
  • Obligatorie pentru dezabonarea de la NotificationCenter și observațiile KVO pentru a evita scurgerile de memorie
  • Se deosebește de viewWillDisappear prin faptul că este apelată după finalizarea animației de tranziție
  • Nu înlocuiește deinit — deinit răspunde de distrugerea finală a obiectului

Ce este viewDidDisappear?

viewDidDisappear — este o metodă hook a superclasei UIViewController, pe care sistemul o apelează după ce vizualizarea (view) a fost complet eliminată din ierarhia ferestrelor de pe ecran. Face parte din ciclul de viață standard al vizualizării în UIKit și oferă dezvoltatorului un punct pentru executarea operațiilor de finalizare.

Metoda este declarată în protocolul UIViewController și este disponibilă pentru suprascriere în toate subclasele. Semnătura metodei: override func viewDidDisappear(_ animated: Bool). Parametrul animated indică dacă tranziția a fost însoțită de animație. Acest lucru permite diferențierea tranzițiilor programatice și animate pentru un control mai precis al comportamentului.

Spre deosebire de viewWillDisappear, care este apelată înainte de începerea animației, viewDidDisappear garantează că vizualizarea nu mai este vizibilă pentru utilizator. Acest lucru este critic pentru operațiile care trebuie executate doar după ascunderea completă a interfeței — de exemplu, ascunderea elementelor overlay pe ecran complet sau finalizarea înregistrării video.

Semnătura și declarația

Metoda este definită în clasa de bază UIViewController și are următoarea semnătură:

swift
import UIKit

class MyViewController: UIViewController {
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        // Eliberarea resurselor și dezabonarea
    }
}

Apelul obligatoriu al super.viewDidDisappear(animated) în prima linie a implementării — este o cerință UIKit. Fără el, superclasa nu poate finaliza corect procesele interne legate de afișarea vizualizării. Ignorarea acestei reguli duce la un comportament imprevizibil al navigării și la potențiale defecțiuni.

Locul viewDidDisappear în ciclul de viață UIViewController

Ciclul de viață complet al UIViewController constă din șase metode cheie, fiecare răspunzând de o anumită fază a existenței vizualizării. viewDidDisappear completează secvența de ascundere, urmând după viewWillDisappear. Este important să înțelegem ordinea de apelare a tuturor metodelor pentru a distribui corect inițializarea și eliberarea resurselor.

Ordinea la apariția vizualizării: viewDidLoadviewWillAppearviewDidAppear. La ascundere: viewWillDisappearviewDidDisappear. Faza finală — deinit, care este apelată la distrugerea obiectului UIViewController. Aceste șase metode formează un ciclu complet, garantând o gestionare previzibilă a stării.

MetodăMomentul apelăriiAplicare tipică
viewDidLoadDupă încărcarea vizualizării în memorieConfigurarea inițială UI, abonarea la date
viewWillAppearÎnainte de apariția vizualizării pe ecranActualizarea datelor înainte de afișare
viewDidAppearDupă apariția vizualizării pe ecranPornirea animațiilor, începerea animației
viewWillDisappearÎnainte de dispariția vizualizăriiSalvarea datelor introduse, anularea operațiilor
viewDidDisappearDupă dispariția vizualizăriiEliberarea resurselor, dezabonarea de la notificări
deinitLa distrugerea obiectuluiCurățarea finală, eliberarea referințelor puternice

Fiecare dintre aceste metode este apelată exact o dată pentru tranziția corespunzătoare. Excepție — viewDidLoad, care poate fi apelată din nou dacă ViewController a fost descărcat din memorie din cauza lipsei de resurse și apoi restaurat. În acest caz, viewDidDisappear va preceda noul viewDidLoad.

Legătura cu animația de tranziție

Parametrul animated din semnătura metodei indică dacă tranziția a fost animată. Acest lucru este util pentru a diferenția tranzițiile programatice fără animație (de exemplu, la setarea rootViewController) de cele animate inițiate de utilizator. Dacă valoarea este false, este posibil ca controlerul să fi fost ascuns forțat de sistem — în acest caz, unele operații dependente de timp pot fi irelevante.

Când este apelată viewDidDisappear

Sistemul apelează viewDidDisappear exact în două scenarii: când ViewController este eliminat din stiva de navigare și când este acoperit de un alt controler. În ambele cazuri, metoda semnalează că vizualizarea nu mai este vizibilă pentru utilizator, iar dezvoltatorul trebuie să elibereze resursele care nu sunt necesare în fundal. Înțelegerea acestor scenarii previne presupunerile greșite despre starea aplicației.

Primul scenariu — pop din UINavigationController. Când utilizatorul apasă butonul „Înapoi”, se apelează popViewController: animated. Controlerul curent primește viewDidDisappear, iar apoi, dacă nu mai există referințe puternice la el, deinit. Al doilea scenariu — present/dismiss. La afișarea modală a unui nou controler, presentingViewController primește viewDidDisappear. La dismiss, această metodă este apelată la controlerul care a fost afișat modal.

Al treilea scenariu, mai puțin evident — adăugarea unui child ViewController. Dacă la un controler container (de exemplu, UIPageViewController sau UITabBarController) se adaugă un nou controler copil, controlerul copil activ primește viewDidDisappear. Acest lucru este critic pentru aplicațiile cu file sau carusele de pagini — fiecare schimbare de filă trebuie să întrerupă corect activitatea ecranului inactiv.

Excepții și cazuri neevidente

Există o excepție importantă: dacă UIViewController este afișat într-o fereastră modală, iar utilizatorul îl închide interactiv printr-o glisare în jos, sistemul poate să nu apeleze viewDidDisappear la o glisare incompletă. Acest comportament a apărut în iOS 13 odată cu dismiss-ul interactiv. Dezvoltatorii trebuie să gestioneze starea prin UIAdaptivePresentationControllerDelegate și metoda didDismiss pentru a primi garantat evenimentul.

O altă caracteristică — avertismentele de memorie. La lipsa de memorie, sistemul poate descărca vizualizarea controlerului care nu este afișată pe ecran. În acest caz, viewDidDisappear este de obicei apelată înainte de descărcare, dar dezvoltatorul ar trebui să dubleze operațiile critic importante de eliberare în didReceiveMemoryWarning pentru siguranță. O astfel de abordare previne pierderea datelor în scenarii extreme.

Scenarii tipice de utilizare

viewDidDisappear este utilizată pentru trei categorii principale de operații: oprirea activităților, eliberarea resurselor și salvarea stării. Fiecare categorie are propriile best practices elaborate de comunitatea dezvoltatorilor iOS. Să analizăm cele mai frecvente scenarii cu exemple de implementare.

  • Oprirea animațiilor — apelarea layer.removeAllAnimations() pentru CALayer, oprirea blocurilor UIView.animate
  • Eliberarea resurselor — anularea imaginilor mari, resetarea datelor din cache, închiderea descriptoarelor de fișiere
  • Dezabonarea de la notificări — eliminarea observatorilor din NotificationCenter.default, oprirea observațiilor KVO
  • Salvarea progresului — scrierea ciornelor în CoreData sau UserDefaults la închiderea ecranului de editare
  • Ascunderea overlay — eliminarea indicatoarelor de încărcare, tooltip-urilor și elementelor popover care nu ar trebui să rămână după tranziție

Exemplu: dezabonarea de la NotificationCenter

O eroare tipică — abonarea la notificări în viewDidLoad și niciodată dezabonarea. Aceasta duce la apelarea handler-ului pe un obiect distrus, ceea ce provoacă un crash. Abordarea corectă — abonarea în viewWillAppear și dezabonarea în viewDidDisappear, ceea ce garantează actualitatea abonării doar în timpul afișării controlerului pe ecran.

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

Acest model garantează că handler-ul de notificări este activ doar când controlerul este vizibil pe ecran. La trecerea la un alt ecran, toate abonările sunt eliminate automat, iar la revenire, sunt restaurate. Acest lucru crește fiabilitatea aplicației și elimină clasa de erori legate de notificări.

Exemple de cod în Swift

Să analizăm două exemple practice de utilizare a viewDidDisappear în proiecte reale. Primul exemplu demonstrează oprirea unui timer la ascunderea ecranului, al doilea — încheierea corectă a observării tastaturii. Ambele exemple urmează principiul eliberării resurselor la inactivitatea controlerului.

Oprirea timer-ului

Dacă pe ecran rulează un Timer pentru actualizarea UI (de exemplu, numărătoare inversă sau carusel), acesta trebuie oprit la ascunderea controlerului. Continuarea funcționării timer-ului în fundal nu doar consumă resursele procesorului, dar poate provoca și o excepție la încercarea de a actualiza un UI invizibil.

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

Pauzarea videoclipului la ascundere

În multe aplicații, AVPlayer redă videoclipuri într-un player încorporat. Dacă utilizatorul trece la un alt ecran, videoclipul trebuie să se pună automat pe pauză. Implementarea în viewDidDisappear garantează că pauza are loc după ascunderea completă a ecranului — acest lucru previne pâlpâirea unui cadru negru la tranziție.

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

Anularea variabilei player după pauză eliberează suplimentar memoria ocupată de bufferele video. Această abordare este deosebit de importantă pentru aplicațiile cu videoclipuri lungi, unde buffer-ul poate ocupa zeci de megaocteți. Combinarea pauzei cu anularea referințelor minimizează amprenta aplicației în fundal.

viewDidDisappear și alte metode ale ciclului de viață

viewDidDisappear este adesea confundată cu viewWillDisappear și deinit, însă fiecare dintre aceste metode are propria zonă de responsabilitate. Înțelegerea granițelor dintre ele este cheia unei arhitecturi stabile a aplicației iOS. Utilizarea incorectă poate duce la eliberarea dublă a resurselor sau, dimpotrivă, la scurgerea acestora.

Principala diferență dintre viewDidDisappear și viewWillDisappear — momentul apelării. viewWillDisappear este apelată când vizualizarea este încă vizibilă, dar se pregătește de dispariție. Acest lucru este potrivit pentru salvarea datelor vizibile (text în câmpurile de intrare). viewDidDisappear este apelată după finalizarea animației, când vizualizarea este garantat invizibilă — ideală pentru eliberarea resurselor nelegate de starea vizuală.

deinit, spre deosebire de viewDidDisappear, este apelată doar la distrugerea obiectului UIViewController în memorie. Dacă controlerul este doar ascuns (de exemplu, acoperit de o fereastră modală), deinit nu este apelat. În această situație, viewDidDisappear este singurul punct pentru executarea operațiilor de finalizare. Eliberarea completă a resurselor ar trebui să aibă loc în deinit, dar viewDidDisappear răspunde de eliberarea temporară până la reapariție.

Când să folosiți fiecare metodă

  • viewWillDisappear — salvarea datelor introduse, trimiterea analiticelor despre începerea tranziției
  • viewDidDisappear — oprirea animațiilor, dezabonarea de la notificări, ascunderea elementelor overlay
  • deinit — eliberarea finală a resurselor mari, închiderea conexiunilor de rețea

În dezvoltarea cu SwiftUI, metoda viewDidDisappear nu se aplică — este înlocuită de modificatorul .onDisappear, care funcționează similar. Cu toate acestea, în SwiftUI nu există un control direct asupra ciclului de viață, iar dezvoltatorii se bazează pe Combine și obiecte State pentru gestionarea resurselor. Pentru aplicațiile UIKit, viewDidDisappear rămâne instrumentul principal de gestionare a ascunderii ecranului.

Erori tipice la implementare

Chiar și dezvoltatorii iOS experimentați fac greșeli în lucrul cu viewDidDisappear. Să analizăm cinci probleme frecvente și modalități de prevenire a acestora. Cunoașterea acestor anti-patterns ajută la evitarea erorilor greu de depistat legate de ciclul de viață al controlerelor.

  • Omisiunea super.viewDidDisappear — apelul super este obligatoriu pentru funcționarea corectă a UIKit, absența sa poate cauza încălcarea stării interne a controlerului
  • Operații grele în viewDidDisappear — scrierea sincronă a datelor mari în viewDidDisappear blochează firul principal și degradează animația de tranziție
  • Dezabonarea uitată de la notificări — dacă removeObserver nu este apelat în viewDidDisappear, handler-ul poate declanșa pe un obiect zombie, cauzând EXC_BAD_ACCESS
  • Dezabonarea dublă — eliminarea unui observator care a fost deja eliminat în altă parte duce la excepția NSInternalInconsistencyException
  • Dependența de ordinea apelării — în containerele imbricate, ordinea apelării viewDidDisappear la controlerele copil și părinte nu este garantată

O atenție deosebită necesită siguranța firelor de execuție. Dacă viewDidDisappear este apelată pe firul principal (ceea ce este garantat de UIKit), dar eliberarea resurselor include operații asincrone, este necesară sincronizarea accesului la datele partajate. Utilizarea DispatchQueue.main.async în interiorul viewDidDisappear pentru actualizarea UI după finalizarea unei sarcini asincrone — este o abordare comună, dar corectă.

Un alt anti-pattern important — apelarea metodelor delegate în interiorul viewDidDisappear care pot iniția o nouă tranziție sau afișare modală. Acest lucru creează un ciclu în care viewDidDisappear poate fi apelată din nou înainte de finalizarea primei apelări. Apple recomandă evitarea afișărilor modale în interiorul metodelor ciclului de viață, mutându-le în handlere separate de evenimente.

Întrebări frecvente

Cu ce se deosebește viewDidDisappear de viewWillDisappear?

viewWillDisappear este apelată înainte de începerea animației de ascundere, când view este încă vizibilă. viewDidDisappear — după dispariția completă a view. Pentru salvarea datelor folosiți viewWillDisappear, pentru eliberarea resurselor — viewDidDisappear.

Este necesar să se apeleze super.viewDidDisappear?

Da, apelul super.viewDidDisappear(animated) este obligatoriu. UIKit folosește această metodă pentru notificări interne și finalizarea stării de tranziție. Fără apelul super, sunt posibile defecțiuni în UINavigationController și UITabBarController.

Poate viewDidDisappear să nu fie apelată?

Da, la dismiss-ul interactiv în iOS 13+ (glisare în jos), metoda poate să nu fie apelată dacă gestul nu este finalizat. Pentru a primi garantat evenimentul, utilizați delegatul UIAdaptivePresentationControllerDelegate și metoda presentationControllerDidDismiss.

Ce este mai bun: viewDidDisappear sau deinit?

deinit este apelată doar la distrugerea obiectului, iar viewDidDisappear la fiecare ascundere. Pentru eliberarea resurselor la fiecare tranziție (de exemplu, dezabonarea de la notificări) folosiți viewDidDisappear. Pentru curățarea finală la eliminarea controlerului — deinit.

Cum funcționează viewDidDisappear în SwiftUI?

În SwiftUI, în loc de viewDidDisappear se utilizează modificatorul .onDisappear { }. Acesta este apelat la ascunderea vizualizării din ierarhie. Spre deosebire de UIKit, SwiftUI nu garantează apelarea onDisappear în toate scenariile în timpul animațiilor.

Rezumat

  • viewDidDisappear — ultima metodă a ciclului de viață înainte de ascundere, apelată după finalizarea animației de tranziție
  • Scopul principal — eliberarea resurselor, oprirea timerelor și dezabonarea de la notificări
  • Apelul obligatoriu al super.viewDidDisappear pentru funcționarea corectă a UIKit
  • Se deosebește de viewWillDisappear prin momentul apelării: după animație, nu înainte
  • Nu înlocuiește deinit — deinit este apelat la distrugerea obiectului, viewDidDisappear la fiecare ascundere
  • Nu se folosește pentru operații sincrone grele — acestea blochează firul principal și perturbă animația
  • În iOS 13+ este necesară procesare suplimentară prin UIAdaptivePresentationControllerDelegate pentru apelarea garantată

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și