viewDidDisappear: суштина методе, животни циклус UIViewController-а и када се позива

Аутор: IT Sectr Објављено: 2026-03-05 Време читања: 9 мин

viewDidDisappear — је метода животног циклуса UIViewController-а која се позива одмах након потпуног нестанка приказа (view) са екрана iOS уређаја. Програмери је користе за заустављање анимација, ослобађање RAM меморије, одјављивање са обавештења и чување тренутног стања. Према Apple Developer Documentation (2025), коректна имплементација ове методе спречава до 40% цурења меморије у апликацијама са активном навигацијом. Без ње, позадински процеси могу наставити са радом, трошећи ресурсе батерије и процесора. Правилна употреба viewDidDisappear-а је једна од кључних вештина iOS програмера која директно утиче на перформансе и стабилност апликације.

Главне тачке

  • viewDidDisappear — коначна метода животног циклуса, позива се након нестанка view-а са екрана
  • Користи се за ослобађање ресурса: заустављање тајмера, скривање индикатора учитавања
  • Обавезна за одјаву са NotificationCenter-а и KVO посматрања ради избегавања цурења меморије
  • Разликује се од viewWillDisappear-а по томе што се позива након завршетка анимације прелаза
  • Не замењује deinit — deinit је одговоран за коначно уништење објекта

Шта је viewDidDisappear?

viewDidDisappear — је метода-кука надкласе UIViewController-а коју систем позива након што је приказ (view) потпуно уклоњен из хијерархије прозора на екрану. Она је део стандардног животног циклуса view-а у UIKit-у и пружа програмеру тачку за извршавање завршних операција.

Метода је декларисана у протоколу UIViewController и доступна је за преклапање у свим подкласама. Сигнатура методе: override func viewDidDisappear(_ animated: Bool). Параметар animated указује да ли је прелаз био праћен анимацијом. Ово омогућава разликовање програмских и анимираних прелаза за прецизнију контролу понашања.

За разлику од viewWillDisappear-а, који се позива пре почетка анимације, viewDidDisappear гарантује да view више није видљив кориснику. Ово је критично за операције које се морају извршити тек након потпуног скривања интерфејса — на пример, скривање прекоцелоекранских overlay елемената или завршетак снимања видеа.

Сигнатура и декларација

Метода је дефинисана у базној класи UIViewController и има следећу сигнатуру:

swift
import UIKit

class MyViewController: UIViewController {
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        // Ослобађање ресурса и одјава
    }
}

Обавезни позив super.viewDidDisappear(animated) у првој линији имплементације — то је захтев UIKit-а. Без њега, надкласа не може коректно да заврши унутрашње процесе везане за приказ view-а. Игнорисање овог правила доводи до непредвидивог понашања навигације и потенцијалних падова.

Место viewDidDisappear-а у животном циклусу UIViewController-а

Потпуни животни циклус UIViewController-а састоји се од шест кључних метода, од којих свака одговара за одређену фазу постојања view-а. viewDidDisappear завршава секвенцу скривања, следећи након viewWillDisappear-а. Важно је разумети редослед позивања свих метода како би се правилно распоредила иницијализација и ослобађање ресурса.

Редослед при појављивању view-а: viewDidLoadviewWillAppearviewDidAppear. При скривању: viewWillDisappearviewDidDisappear. Завршна фаза — deinit, који се позива при уништењу објекта UIViewController-а. Ових шест метода чине комплетан циклус, гарантујући предвидиво управљање стањем.

МетодаТренутак позивањаТипична примена
viewDidLoadНакон учитавања view-а у меморијуПочетно подешавање UI-а, претплата на податке
viewWillAppearПре појављивања view-а на екрануАжурирање података пре приказа
viewDidAppearНакон појављивања view-а на екрануПокретање анимација, почетак анимације
viewWillDisappearПре нестанка view-аЧување унетих података, отказивање операција
viewDidDisappearНакон нестанка view-аОслобађање ресурса, одјава са обавештења
deinitПри уништењу објектаКоначно чишћење, ослобађање јаких референци

Свака од ових метода позива се тачно једном за одговарајући прелаз. Изузетак — viewDidLoad, који се може поново позвати ако је ViewController истоварен из меморије због недостатка ресурса, а затим обновљен. У том случају, viewDidDisappear ће претходити поновном viewDidLoad-у.

Веза са анимацијом прелаза

Параметар animated у сигнатури методе указује да ли је прелаз био анимиран. Ово је корисно за разликовање програмских прелаза без анимације (на пример, при постављању rootViewController-а) и анимираних прелаза покренутих од стране корисника. Ако је вредност false, могуће је да је контролер присилно сакривен од стране система — у том случају, неке операције зависне од времена могу бити нерелевантне.

Када се позива viewDidDisappear

Систем позива viewDidDisappear тачно у два сценарија: када се ViewController уклања из стека навигације и када га прекрива други контролер. У оба случаја, метода сигнализира да view више није видљив кориснику и програмер треба да ослободи ресурсе који нису потребни у позадини. Разумевање ових сценарија спречава погрешне претпоставке о стању апликације.

Први сценарио — pop из UINavigationController-а. Када корисник притисне дугме „Назад”, позива се popViewController: animated. Тренутни контролер добија viewDidDisappear, а затим, ако на њега више нема јаких референци, deinit. Други сценарио — present/dismiss. При модалном приказивању новог контролера, presentingViewController добија viewDidDisappear. При dismiss-у, ова метода се позива код контролера који је приказан модално.

Трећи, мање очигледан сценарио — додавање child ViewController-а. Ако се у контејнерски контролер (на пример, UIPageViewController или UITabBarController) дода нови контролер дете, активни контролер дете добија viewDidDisappear. Ово је критично за апликације са картицама или каруселима страница — свака промена картице мора коректно да заустави рад неактивног екрана.

Изузеци и неочигледни случајеви

Постоји важан изузетак: ако је UIViewController приказан у модалном прозору и корисник га затвара превлачењем надоле, систем можда неће позвати viewDidDisappear при непотпуним превлачењу. Ово понашање се појавило у iOS 13 заједно са интерактивним dismiss-ом. Програмери треба да управљају стањем путем UIAdaptivePresentationControllerDelegate и методе didDismiss ради гарантованог пријема догађаја.

Још једна карактеристика — упозорења о меморији. При недостатку меморије, систем може да истовари view контролера који није приказан на екрану. У овом случају, viewDidDisappear се обично позива пре истоварања, али програмер треба да дуплира критично важне операције ослобађања у didReceiveMemoryWarning за сигурност. Овакав приступ спречава губитак података у екстремним сценаријима.

Типични сценарији употребе

viewDidDisappear се користи за три главне категорије операција: заустављање активности, ослобађање ресурса и чување стања. Свака категорија има своје best practices које је развила заједница iOS програмера. Размотримо најчешће сценарије са примерима имплементације.

  • Заустављање анимација — позив layer.removeAllAnimations() за CALayer, заустављање UIView.animate блокова
  • Ослобађање ресурса — поништавање великих слика, ресетовање кешираних података, затварање дескриптора датотека
  • Одјава са обавештења — уклањање посматрача из NotificationCenter.default, заустављање KVO посматрања
  • Чување напретка — упис нацрта у CoreData или UserDefaults при затварању екрана за уређивање
  • Скривање overlay-а — уклањање индикатора учитавања, савета и popover елемената који не би требало да остану након прелаза

Пример: одјава са NotificationCenter-а

Типична грешка — претплата на обавештења у viewDidLoad-у и никада се не одјавити. Ово доводи до позива handler-а на уништеном објекту, што изазива crash. Исправан приступ — претплата у viewWillAppear-у и одјава у viewDidDisappear-у, што гарантује актуелност претплате само током приказа контролера на екрану.

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

Овај образац гарантује да је handler обавештења активан само када је контролер видљив на екрану. При преласку на други екран, све претплате се аутоматски уклањају, а при повратку обнављају. Ово повећава поузданост апликације и елиминише класу грешака везаних за обавештења.

Примери кода у Swift-у

Размотримо два практична примера употребе viewDidDisappear-а у реалним пројектима. Први пример демонстрира заустављање тајмера при скривању екрана, други — коректно завршавање посматрања тастатуре. Оба примера следе принцип ослобађања ресурса при неактивности контролера.

Заустављање тајмера

Ако на екрану ради Timer за ажурирање UI-а (на пример, одбројавање или карусел), потребно га је зауставити при скривању контролера. Наставак рада тајмера у позадини не само да троши ресурсе процесора, већ може изазвати изузетак при покушају ажурирања невидљивог 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
    }
}

Паузирање видеа при скривању

У многим апликацијама AVPlayer репродукује видео у уграђеном плејеру. Ако корисник пређе на други екран, видео треба аутоматски да се паузира. Имплементација у viewDidDisappear-у гарантује да се пауза дешава након потпуног скривања екрана — ово спречава треперење црног оквира при прелазу.

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

Поништавање променљиве player након паузе додатно ослобађа меморију заузету видео баферима. Овај приступ је посебно важан за апликације са дугим видео снимцима, где бафер може заузимати десетине мегабајта. Комбинација паузе са поништавањем референци минимизира отисак апликације у позадини.

viewDidDisappear и друге методе животног циклуса

viewDidDisappear се често меша са viewWillDisappear и deinit, али свака од ових метода има своју зону одговорности. Разумевање граница између њих је кључ стабилне архитектуре iOS апликације. Неправилна употреба може довести до двоструког ослобађања ресурса или, обрнуто, до њиховог цурења.

Главна разлика viewDidDisappear-а од viewWillDisappear-а — тренутак позивања. viewWillDisappear се позива када је view још увек видљив, али се већ припрема за нестанак. Ово је погодно за чување видљивих података (текст у пољима за унос). viewDidDisappear се позива након завршетка анимације, када је view гарантовано невидљив — идеално за ослобађање ресурса који нису повезани са визуелним стањем.

deinit, за разлику од viewDidDisappear-а, позива се само при уништењу објекта UIViewController-а у меморији. Ако је контролер само сакривен (на пример, прекривен модалним прозором), deinit се не позива. У овој ситуацији, viewDidDisappear је једина тачка за извршавање завршних операција. Потпуно ослобађање ресурса треба да се деси у deinit-у, али viewDidDisappear је одговоран за привремено ослобађање до поновног појављивања.

Када користити коју методу

  • viewWillDisappear — чување унетих података, слање аналитике о почетку прелаза
  • viewDidDisappear — заустављање анимација, одјава са обавештења, скривање overlay елемената
  • deinit — коначно ослобађање великих ресурса, затварање мрежних веза

При развоју са SwiftUI методом viewDidDisappear се не користи — замењује је модификатор .onDisappear, који ради на сличан начин. Међутим, у SwiftUI-ју не постоји директна контрола над животним циклусом, и програмери се ослањају на Combine и State објекте за управљање ресурсима. За UIKit апликације, viewDidDisappear остаје основни алат за управљање скривањем екрана.

Типичне грешке при имплементацији

Чак и искусни iOS програмери праве грешке у раду са viewDidDisappear-ом. Размотримо пет најчешћих проблема и начине њиховог спречавања. Познавање ових анти-образаца помаже у избегавању тешко уочљивих грешака везаних за животни циклус контролера.

  • Изостављање super.viewDidDisappear — позив super је обавезан за коректан рад UIKit-а, његово одсуство може изазвати нарушавање унутрашњег стања контролера
  • Тешке операције у viewDidDisappear-у — синхрони упис великих података у viewDidDisappear-у блокира главну нит и погоршава анимацију прелаза
  • Заборављена одјава са обавештења — ако се removeObserver не позове у viewDidDisappear-у, handler може да се активира на zombie објекту, изазивајући EXC_BAD_ACCESS
  • Двострука одјава — уклањање посматрача који је већ уклоњен на другом месту доводи до изузетка NSInternalInconsistencyException
  • Зависност од редоследа позивања — у угњежденим контејнерима, редослед позивања viewDidDisappear-а код дете и родитељ контролера није гарантован

Посебну пажњу захтева безбедност нити. Ако се viewDidDisappear позива на главној нити (што UIKit гарантује), али ослобађање ресурса укључује асинхроне операције, потребно је синхронизовати приступ дељеним подацима. Коришћење DispatchQueue.main.async унутар viewDidDisappear-а за ажурирање UI-а након завршетка асинхроног задатка — уобичајен је, али исправан приступ.

Још један важан анти-образац — позивање делегатских метода унутар viewDidDisappear-а које могу покренути нови прелаз или модални приказ. Ово ствара циклус у којем viewDidDisappear може бити поново позван пре завршетка првог позива. Apple препоручује избегавање модалних приказа унутар метода животног циклуса, измештајући их у засебне руковаоце догађајима.

Често постављана питања

По чему се viewDidDisappear разликује од viewWillDisappear-а?

viewWillDisappear се позива пре почетка анимације скривања, када је view још видљив. viewDidDisappear — након потпуног нестанка view-а. За чување података користите viewWillDisappear, за ослобађање ресурса — viewDidDisappear.

Да ли је потребно позвати super.viewDidDisappear?

Да, позив super.viewDidDisappear(animated) је обавезан. UIKit користи ову методу за унутрашња обавештења и завршетак стања прелаза. Без позива super могући су падови у UINavigationController-у и UITabBarController-у.

Може ли viewDidDisappear да се не позове?

Да, при интерактивном dismiss-у у iOS 13+ (превлачење надоле) метода се можда неће позвати ако гест није завршен. За гарантовани пријем догађаја користите делегата UIAdaptivePresentationControllerDelegate и методу presentationControllerDidDismiss.

Шта је боље: viewDidDisappear или deinit?

deinit се позива само при уништењу објекта, док се viewDidDisappear позива при сваком скривању. За ослобађање ресурса при сваком прелазу (на пример, одјава са обавештења) користите viewDidDisappear. За коначно чишћење при уклањању контролера — deinit.

Како viewDidDisappear ради у SwiftUI-ју?

У SwiftUI се уместо viewDidDisappear-а користи модификатор .onDisappear { }. Он се позива при скривању view-а из хијерархије. За разлику од UIKit-а, SwiftUI не гарантује позив onDisappear-а у свим сценаријима током анимација.

Резиме

  • viewDidDisappear — последња метода животног циклуса пре скривања, позива се након завршетка анимације прелаза
  • Основна намена — ослобађање ресурса, заустављање тајмера и одјава са обавештења
  • Обавезни позив super.viewDidDisappear за коректан рад UIKit-а
  • Разликује се од viewWillDisappear-а по тренутку позивања: након анимације, а не пре ње
  • Не замењује deinit — deinit се позива при уништењу објекта, viewDidDisappear при сваком скривању
  • Не користи се за тешке синхроне операције — one блокирају главну нит и нарушавају анимацију
  • У iOS 13+ потребна је додатна обрада путем UIAdaptivePresentationControllerDelegate-а за гарантовани позив

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође