UIViewController — централна класа iOS апликације, која управља екраном и његовим садржајем. Сваки екран iPhone-а или iPad-а управља се једним ViewController-ом, који координира приказ, животни циклус и навигацију. Више о архитектури UIKit прочитајте у званичној документацији Apple-а.
Главно
UIViewController — класа из UIKit оквира која управља UIView хијерархијом и координира приказ података на екрану. Свака iOS апликација садржи најмање један ViewController — коренски контролер прозора. Контролер обрађује ротације екрана, прелазе између екрана и догађаје животног циклуса.
MVC (Model-View-Controller) архитектура у iOS-у је имплементирана управо кроз UIViewController: контролер прима податке од модела и ажурира приказ. ViewController није визуелни елемент — он управља својством view које садржи хијерархију subview-ова. Према Apple-овим подацима (2026), UIKit садржи преко 40 уграђених подкласа UIViewController-а.
Први iPhone SDK (2008) је укључивао UIViewController са три метода животног циклуса. Током 18 година Apple је додао подршку за Container View Controller, адаптивне презентације, UIViewControllerTransitioningDelegate за прилагођене анимације и режим подељеног екрана на iPad-у. UIViewController остаје обавезна компонента за UIKit апликације.
Животни циклус UIViewController-а — секвенца метода које систем позива при креирању, приказивању и скривању екрана. Разумевање животног циклуса је критично: неправилно постављање кода доводи до цурења меморије, непотребних мрежних захтева и треперења интерфејса.
| Метод | Тренутак позива | Намена |
|---|---|---|
| viewDidLoad | Једном, након учитавања view-а у меморију | Почетно подешавање UI-ја, претплата на Combine |
| viewWillAppear | Пре појављивања екрана | Ажурирање података, скривање/приказ navigation bar-а |
| viewDidAppear | Након појављивања екрана | Покретање анимација, аналитика, ажурирање камере |
| viewWillDisappear | Пре напуштања екрана | Чување скица, одјава са обавештења |
| viewDidDisappear | Након напуштања екрана | Заустављање тешких процеса, ослобађање ресурса |
При првом приказу екрана секвенца: init → loadView → viewDidLoad → viewWillAppear → viewDidAppear. При поновном појављивању (повратак са другог екрана): viewWillAppear → viewDidAppear. viewDidLoad се позива само једном током живота контролера.
Метод viewDidLoad — главна тачка подешавања корисничког интерфејса. Позива се након учитавања view-а у меморију, када су сви IBOutlet-и већ повезани. Овде се креирају UI елементи програмски, подешавају constraints, учитавају почетни подаци.
final class ProfileViewController: UIViewController {
private let tableView = UITableView()
private let viewModel = ProfileViewModel()
override func viewDidLoad() {
super.viewDidLoad()
setupUI()
bindViewModel()
}
private func setupUI() {
view.addSubview(tableView)
tableView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
])
tableView.register(ProfileCell.self,
forCellReuseIdentifier: ProfileCell.reuseId)
}
private func bindViewModel() {
viewModel.$user
.receive(on: DispatchQueue.main)
.sink { [weak self] user in
self?.title = user.name
}
.store(in: &cancellables)
}
}У SwiftUI-ју овај код је еквивалентан телу View-а. Али UIViewController даје потпуну контролу над животним циклусом и оптимизацијом. bindViewModel користи Combine за реактивну претплату — подаци се аутоматски ажурирају при промени модела.
viewWillAppear се позива сваки пут пре појављивања екрана, чак и ако је већ био у меморији. Ово је место за ажурирање података који су се могли променити на другом екрану: поновно учитавање листе, ажурирање бројача обавештења, подешавање navigation bar-а за конкретан екран.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Сакривамо navigation bar на овом екрану
navigationController?.setNavigationBarHidden(true, animated: animated)
// Ажурирамо податке при повратку са другог екрана
tableView.reloadData()
badgeLabel.text = "\(CartManager.shared.itemCount)"
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// Аналитика: тек након што је корисник видео екран
AnalyticsService.shared.logScreenView("Profile")
}Разлика између viewDidLoad и viewWillAppear је критична: viewDidLoad се извршава једном и погодан је за статичко подешавање, viewWillAppear — сваки пут при приказу, погодан за динамичка ажурирања. Постављање мрежних захтева у viewDidLoad довешће до приказа застарелих података при повратку на екран.
Container View Controller — ViewController који управља једним или више подређених ViewController-а. Apple пружа три уграђена контејнера: UINavigationController (стек екрана), UITabBarController (картице) и UISplitViewController (master-detail за iPad).
UINavigationController организује прелазе у стек — push додаје екран, pop уклања. UITabBarController пребацује између независних секција апликације. UISplitViewController приказује два контролера један поред другог на iPad-у и један на iPhone-у. Програмер може креирати сопствени контејнер кроз addChild.
// Прилагођени Container View Controller
final class ContainerViewController: UIViewController {
private let sidebarVC = SidebarViewController()
private let contentVC = ContentViewController()
override func viewDidLoad() {
super.viewDidLoad()
// Додавање подређеног контролера
addChild(sidebarVC)
view.addSubview(sidebarVC.view)
sidebarVC.didMove(toParent: self)
addChild(contentVC)
view.addSubview(contentVC.view)
contentVC.didMove(toParent: self)
}
}Исправан рад са Container View Controller-ом захтева позив addChild, додавање view-а и didMove(toParent:) овим редом. При уклањању — willMove(toParent: nil), removeFromSuperview, removeFromParent. Кршење редоследа доводи до цурења меморије.
Проблем Massive View Controller-а — када UIViewController садржи стотине линија кода са пословном логиком, мрежним захтевима, навигацијом и UI кодом. Apple је свестан проблема и препоручује MVVM (Model-View-ViewModel) заједно са Coordinator-ом за раздвајање навигације.
MVVM премешта пословну логику из контролера у ViewModel. Controller само повезује ViewModel са View-ом преко Combine-а или делегата. Coordinator издваја навигациону логику — креирање и прелазе између контролера — у засебну класу. Овај приступ је уврштен у Apple-ове најбоље праксе од 2024. године.
// Coordinator — управљање навигацијом
protocol Coordinator {
var childCoordinators: [Coordinator] { get set }
func start()
}
final class MainCoordinator: Coordinator {
var childCoordinators = [Coordinator]()
private let navigationController: UINavigationController
init(navigationController: UINavigationController) {
self.navigationController = navigationController
}
func start() {
let vc = ListViewController()
vc.didSelectItem = { [weak self] item in
self?.showDetail(item)
}
navigationController.pushViewController(vc, animated: false)
}
private func showDetail(_ item: Item) {
let vc = DetailViewController(item: item)
navigationController.pushViewController(vc, animated: true)
}
}Избор између UIViewController-а и SwiftUI View-а зависи од године почетка пројекта, захтева за прилагођавањем и минималне подржане iOS верзије. UIKit са UIViewController-ом остаје основа за пројекте започете пре 2020. године и за апликације са дубоким прилагођавањем интерфејса.
SwiftUI је погодан за нове пројекте са iOS 17+, стандардне интерфејсе и прототипове. Међутим, за прилагођене прелазе, рад са камером, MapKit, сложене CALayer анимације потребан је UIViewController. Apple препоручује комбиновање приступа кроз UIHostingController (SwiftUI унутар UIKit-а) и UIViewRepresentable (UIKit унутар SwiftUI-ја).
| Сценарио | UIKit (UIViewController) | SwiftUI (View) |
|---|---|---|
| Прилагођена анимација | Потпуна контрола кроз UIViewPropertyAnimator | Ограничена кроз Animation |
| Рад са камером | AVCaptureSession + UIViewPreview | Кроз UIViewControllerRepresentable |
| CollectionView | UICollectionView + UICollectionViewLayout | LazyVGrid/LazyHGrid |
| Адаптација iPad | UISplitViewController + UITraitCollection | NavigationSplitView + sizeClass |
| Брзина развоја | Спорије (ручни layout) | Брже (декларативно) |
Често постављана питања
UIViewController — контролер који управља екраном и његовим животним циклусом. UIView — приказ који приказује садржај. ViewController садржи UIView хијерархију, али сам није визуелни елемент. Један контролер управља са много приказа.
Massive View Controller — антиобразац када UIViewController садржи превише логике: податке, навигацију, мрежне захтеве, анимације. Решење — издвајање кода у засебне сервисе, координаторе и ViewModel (MVVM).
Четири начина: преко својства при prepare(for:sender:) (Segue), преко делегата (Delegate), преко затварања (Closure), преко заједничког сервиса. За слабу повезаност користи се Coordinator + Delegate или Combine.
Container View Controller — контролер који управља подређеним ViewController-има. Примери: UINavigationController, UITabBarController, UISplitViewController. Родитељски контролер додаје подређене кроз addChild, пребацује се између њих и управља њиховим layout-ом.
UIViewController — за сложене прилагођене анимације, рад са камером, мапом, видеом, UICollectionView са прилагођеним layout-ом. SwiftUI View — за стандардне интерфејсе iOS 13+. Комбиновање кроз UIHostingController је дозвољено.
Резиме
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође