viewDidDisappear — је метода животног циклуса UIViewController-а која се позива одмах након потпуног нестанка приказа (view) са екрана iOS уређаја. Програмери је користе за заустављање анимација, ослобађање RAM меморије, одјављивање са обавештења и чување тренутног стања. Према Apple Developer Documentation (2025), коректна имплементација ове методе спречава до 40% цурења меморије у апликацијама са активном навигацијом. Без ње, позадински процеси могу наставити са радом, трошећи ресурсе батерије и процесора. Правилна употреба viewDidDisappear-а је једна од кључних вештина iOS програмера која директно утиче на перформансе и стабилност апликације.
Главне тачке
viewDidDisappear — је метода-кука надкласе UIViewController-а коју систем позива након што је приказ (view) потпуно уклоњен из хијерархије прозора на екрану. Она је део стандардног животног циклуса view-а у UIKit-у и пружа програмеру тачку за извршавање завршних операција.
Метода је декларисана у протоколу UIViewController и доступна је за преклапање у свим подкласама. Сигнатура методе: override func viewDidDisappear(_ animated: Bool). Параметар animated указује да ли је прелаз био праћен анимацијом. Ово омогућава разликовање програмских и анимираних прелаза за прецизнију контролу понашања.
За разлику од viewWillDisappear-а, који се позива пре почетка анимације, viewDidDisappear гарантује да view више није видљив кориснику. Ово је критично за операције које се морају извршити тек након потпуног скривања интерфејса — на пример, скривање прекоцелоекранских overlay елемената или завршетак снимања видеа.
Метода је дефинисана у базној класи UIViewController и има следећу сигнатуру:
import UIKit
class MyViewController: UIViewController {
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
// Ослобађање ресурса и одјава
}
}
Обавезни позив super.viewDidDisappear(animated) у првој линији имплементације — то је захтев UIKit-а. Без њега, надкласа не може коректно да заврши унутрашње процесе везане за приказ view-а. Игнорисање овог правила доводи до непредвидивог понашања навигације и потенцијалних падова.
Потпуни животни циклус UIViewController-а састоји се од шест кључних метода, од којих свака одговара за одређену фазу постојања view-а. viewDidDisappear завршава секвенцу скривања, следећи након viewWillDisappear-а. Важно је разумети редослед позивања свих метода како би се правилно распоредила иницијализација и ослобађање ресурса.
Редослед при појављивању view-а: viewDidLoad → viewWillAppear → viewDidAppear. При скривању: viewWillDisappear → viewDidDisappear. Завршна фаза — deinit, који се позива при уништењу објекта UIViewController-а. Ових шест метода чине комплетан циклус, гарантујући предвидиво управљање стањем.
| Метода | Тренутак позивања | Типична примена |
|---|---|---|
| viewDidLoad | Након учитавања view-а у меморију | Почетно подешавање UI-а, претплата на податке |
| viewWillAppear | Пре појављивања view-а на екрану | Ажурирање података пре приказа |
| viewDidAppear | Након појављивања view-а на екрану | Покретање анимација, почетак анимације |
| viewWillDisappear | Пре нестанка view-а | Чување унетих података, отказивање операција |
| viewDidDisappear | Након нестанка view-а | Ослобађање ресурса, одјава са обавештења |
| deinit | При уништењу објекта | Коначно чишћење, ослобађање јаких референци |
Свака од ових метода позива се тачно једном за одговарајући прелаз. Изузетак — viewDidLoad, који се може поново позвати ако је ViewController истоварен из меморије због недостатка ресурса, а затим обновљен. У том случају, viewDidDisappear ће претходити поновном viewDidLoad-у.
Параметар animated у сигнатури методе указује да ли је прелаз био анимиран. Ово је корисно за разликовање програмских прелаза без анимације (на пример, при постављању rootViewController-а) и анимираних прелаза покренутих од стране корисника. Ако је вредност false, могуће је да је контролер присилно сакривен од стране система — у том случају, неке операције зависне од времена могу бити нерелевантне.
Систем позива 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 програмера. Размотримо најчешће сценарије са примерима имплементације.
Типична грешка — претплата на обавештења у viewDidLoad-у и никада се не одјавити. Ово доводи до позива handler-а на уништеном објекту, што изазива crash. Исправан приступ — претплата у viewWillAppear-у и одјава у viewDidDisappear-у, што гарантује актуелност претплате само током приказа контролера на екрану.
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 обавештења активан само када је контролер видљив на екрану. При преласку на други екран, све претплате се аутоматски уклањају, а при повратку обнављају. Ово повећава поузданост апликације и елиминише класу грешака везаних за обавештења.
Размотримо два практична примера употребе viewDidDisappear-а у реалним пројектима. Први пример демонстрира заустављање тајмера при скривању екрана, други — коректно завршавање посматрања тастатуре. Оба примера следе принцип ослобађања ресурса при неактивности контролера.
Ако на екрану ради Timer за ажурирање UI-а (на пример, одбројавање или карусел), потребно га је зауставити при скривању контролера. Наставак рада тајмера у позадини не само да троши ресурсе процесора, већ може изазвати изузетак при покушају ажурирања невидљивог UI-а.
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-у гарантује да се пауза дешава након потпуног скривања екрана — ово спречава треперење црног оквира при прелазу.
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
if player().timeControlStatus == .playing {
player().pause()
playerLayer().removeFromSuperlayer()
}
player = nil
}
Поништавање променљиве player након паузе додатно ослобађа меморију заузету видео баферима. Овај приступ је посебно важан за апликације са дугим видео снимцима, где бафер може заузимати десетине мегабајта. Комбинација паузе са поништавањем референци минимизира отисак апликације у позадини.
viewDidDisappear се често меша са viewWillDisappear и deinit, али свака од ових метода има своју зону одговорности. Разумевање граница између њих је кључ стабилне архитектуре iOS апликације. Неправилна употреба може довести до двоструког ослобађања ресурса или, обрнуто, до њиховог цурења.
Главна разлика viewDidDisappear-а од viewWillDisappear-а — тренутак позивања. viewWillDisappear се позива када је view још увек видљив, али се већ припрема за нестанак. Ово је погодно за чување видљивих података (текст у пољима за унос). viewDidDisappear се позива након завршетка анимације, када је view гарантовано невидљив — идеално за ослобађање ресурса који нису повезани са визуелним стањем.
deinit, за разлику од viewDidDisappear-а, позива се само при уништењу објекта UIViewController-а у меморији. Ако је контролер само сакривен (на пример, прекривен модалним прозором), deinit се не позива. У овој ситуацији, viewDidDisappear је једина тачка за извршавање завршних операција. Потпуно ослобађање ресурса треба да се деси у deinit-у, али viewDidDisappear је одговоран за привремено ослобађање до поновног појављивања.
При развоју са SwiftUI методом viewDidDisappear се не користи — замењује је модификатор .onDisappear, који ради на сличан начин. Међутим, у SwiftUI-ју не постоји директна контрола над животним циклусом, и програмери се ослањају на Combine и State објекте за управљање ресурсима. За UIKit апликације, viewDidDisappear остаје основни алат за управљање скривањем екрана.
Чак и искусни iOS програмери праве грешке у раду са viewDidDisappear-ом. Размотримо пет најчешћих проблема и начине њиховог спречавања. Познавање ових анти-образаца помаже у избегавању тешко уочљивих грешака везаних за животни циклус контролера.
Посебну пажњу захтева безбедност нити. Ако се viewDidDisappear позива на главној нити (што UIKit гарантује), али ослобађање ресурса укључује асинхроне операције, потребно је синхронизовати приступ дељеним подацима. Коришћење DispatchQueue.main.async унутар viewDidDisappear-а за ажурирање UI-а након завршетка асинхроног задатка — уобичајен је, али исправан приступ.
Још један важан анти-образац — позивање делегатских метода унутар viewDidDisappear-а које могу покренути нови прелаз или модални приказ. Ово ствара циклус у којем viewDidDisappear може бити поново позван пре завршетка првог позива. Apple препоручује избегавање модалних приказа унутар метода животног циклуса, измештајући их у засебне руковаоце догађајима.
Често постављана питања
viewWillDisappear се позива пре почетка анимације скривања, када је view још видљив. viewDidDisappear — након потпуног нестанка view-а. За чување података користите viewWillDisappear, за ослобађање ресурса — viewDidDisappear.
Да, позив super.viewDidDisappear(animated) је обавезан. UIKit користи ову методу за унутрашња обавештења и завршетак стања прелаза. Без позива super могући су падови у UINavigationController-у и UITabBarController-у.
Да, при интерактивном dismiss-у у iOS 13+ (превлачење надоле) метода се можда неће позвати ако гест није завршен. За гарантовани пријем догађаја користите делегата UIAdaptivePresentationControllerDelegate и методу presentationControllerDidDismiss.
deinit се позива само при уништењу објекта, док се viewDidDisappear позива при сваком скривању. За ослобађање ресурса при сваком прелазу (на пример, одјава са обавештења) користите viewDidDisappear. За коначно чишћење при уклањању контролера — deinit.
У SwiftUI се уместо viewDidDisappear-а користи модификатор .onDisappear { }. Он се позива при скривању view-а из хијерархије. За разлику од UIKit-а, SwiftUI не гарантује позив onDisappear-а у свим сценаријима током анимација.
Резиме
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође