ViewController — суштина, контролер екрана у iOS и његов Lifecycle

Аутор: IT Sectr Објављено: 2026-02-22 Време читања: 7 мин

UIViewController — централна класа iOS апликације, која управља екраном и његовим садржајем. Сваки екран iPhone-а или iPad-а управља се једним ViewController-ом, који координира приказ, животни циклус и навигацију. Више о архитектури UIKit прочитајте у званичној документацији Apple-а.

Главно

  • UIViewController — базна класа за управљање екраном у UIKit-у са сопственим животним циклусом
  • viewDidLoad — позива се једном, тачка иницијализације UI-ја и претплате на податке
  • viewWillAppear — екран ће ускоро постати видљив, ажурирање података пре приказа
  • Lifecycle укључује пет метода: viewDidLoad, viewWillAppear, viewDidAppear, viewWillDisappear, viewDidDisappear
  • Massive View Controller — главни антиобразац iOS-а, решава се кроз MVVM или Coordinator

Шта је ViewController?

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

Животни циклус UIViewController-а — секвенца метода које систем позива при креирању, приказивању и скривању екрана. Разумевање животног циклуса је критично: неправилно постављање кода доводи до цурења меморије, непотребних мрежних захтева и треперења интерфејса.

МетодТренутак позиваНамена
viewDidLoadЈедном, након учитавања view-а у меморијуПочетно подешавање UI-ја, претплата на Combine
viewWillAppearПре појављивања екранаАжурирање података, скривање/приказ navigation bar-а
viewDidAppearНакон појављивања екранаПокретање анимација, аналитика, ажурирање камере
viewWillDisappearПре напуштања екранаЧување скица, одјава са обавештења
viewDidDisappearНакон напуштања екранаЗаустављање тешких процеса, ослобађање ресурса

Редослед позива при појављивању екрана

При првом приказу екрана секвенца: init → loadView → viewDidLoad → viewWillAppear → viewDidAppear. При поновном појављивању (повратак са другог екрана): viewWillAppear → viewDidAppear. viewDidLoad се позива само једном током живота контролера.

viewDidLoad, init и подешавање UI-ја

Метод viewDidLoad — главна тачка подешавања корисничког интерфејса. Позива се након учитавања view-а у меморију, када су сви IBOutlet-и већ повезани. Овде се креирају UI елементи програмски, подешавају constraints, учитавају почетни подаци.

swift
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 и ажурирање података

viewWillAppear се позива сваки пут пре појављивања екрана, чак и ако је већ био у меморији. Ово је место за ажурирање података који су се могли променити на другом екрану: поновно учитавање листе, ажурирање бројача обавештења, подешавање navigation bar-а за конкретан екран.

swift
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: UINavigationController и UITabBarController

Container View Controller — ViewController који управља једним или више подређених ViewController-а. Apple пружа три уграђена контејнера: UINavigationController (стек екрана), UITabBarController (картице) и UISplitViewController (master-detail за iPad).

UINavigationController организује прелазе у стек — push додаје екран, pop уклања. UITabBarController пребацује између независних секција апликације. UISplitViewController приказује два контролера један поред другог на iPad-у и један на iPhone-у. Програмер може креирати сопствени контејнер кроз addChild.

swift
// Прилагођени 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-а кроз MVVM и Coordinator

Проблем Massive View Controller-а — када UIViewController садржи стотине линија кода са пословном логиком, мрежним захтевима, навигацијом и UI кодом. Apple је свестан проблема и препоручује MVVM (Model-View-ViewModel) заједно са Coordinator-ом за раздвајање навигације.

MVVM премешта пословну логику из контролера у ViewModel. Controller само повезује ViewModel са View-ом преко Combine-а или делегата. Coordinator издваја навигациону логику — креирање и прелазе између контролера — у засебну класу. Овај приступ је уврштен у Apple-ове најбоље праксе од 2024. године.

swift
// 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 vs SwiftUI: када шта изабрати

Избор између 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
CollectionViewUICollectionView + UICollectionViewLayoutLazyVGrid/LazyHGrid
Адаптација iPadUISplitViewController + UITraitCollectionNavigationSplitView + sizeClass
Брзина развојаСпорије (ручни layout)Брже (декларативно)

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

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

UIViewController — контролер који управља екраном и његовим животним циклусом. UIView — приказ који приказује садржај. ViewController садржи UIView хијерархију, али сам није визуелни елемент. Један контролер управља са много приказа.

Шта је Massive View Controller?

Massive View Controller — антиобразац када UIViewController садржи превише логике: податке, навигацију, мрежне захтеве, анимације. Решење — издвајање кода у засебне сервисе, координаторе и ViewModel (MVVM).

Како пренети податке између ViewController-а?

Четири начина: преко својства при prepare(for:sender:) (Segue), преко делегата (Delegate), преко затварања (Closure), преко заједничког сервиса. За слабу повезаност користи се Coordinator + Delegate или Combine.

Шта је Container View Controller?

Container View Controller — контролер који управља подређеним ViewController-има. Примери: UINavigationController, UITabBarController, UISplitViewController. Родитељски контролер додаје подређене кроз addChild, пребацује се између њих и управља њиховим layout-ом.

Када користити UIViewController уместо SwiftUI View-а?

UIViewController — за сложене прилагођене анимације, рад са камером, мапом, видеом, UICollectionView са прилагођеним layout-ом. SwiftUI View — за стандардне интерфејсе iOS 13+. Комбиновање кроз UIHostingController је дозвољено.

Резиме

  • UIViewController — централна UIKit класа за управљање екраном, UIView хијерархијом и животним циклусом
  • Животни циклус се састоји од пет метода: viewDidLoad, viewWillAppear, viewDidAppear, viewWillDisappear, viewDidDisappear
  • viewDidLoad — тачка почетног подешавања UI-ја, позива се једном током живота контролера
  • viewWillAppear — позива се сваки пут пре приказа, погодан за ажурирање података и подешавање navigation bar-а
  • Container View Controller (UINavigationController, UITabBarController) управља хијерархијом подређених контролера
  • Massive View Controller се решава кроз MVVM (издвајање логике у ViewModel) и Coordinator (издвајање навигације)
  • UIViewController и SwiftUI се могу комбиновати кроз UIHostingController и UIViewRepresentable за хибридне апликације

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

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

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

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