ViewController — esensi, pengontrol layar di iOS dan siklus hidupnya

Penulis: IT Sectr Diterbitkan: 2026-02-22 Waktu membaca: 7 mnt

UIViewController — kelas sentral aplikasi iOS, mengelola layar dan isinya. Setiap layar iPhone atau iPad dikelola oleh satu ViewController yang mengoordinasikan tampilan, siklus hidup, dan navigasi. Baca lebih lanjut tentang arsitektur UIKit di dokumentasi resmi Apple.

Poin utama

  • UIViewController — kelas dasar untuk mengelola layar di UIKit dengan siklus hidup sendiri
  • viewDidLoad — dipanggil sekali, titik inisialisasi UI dan langganan data
  • viewWillAppear — layar akan segera terlihat, pembaruan data sebelum ditampilkan
  • Siklus hidup mencakup lima metode: viewDidLoad, viewWillAppear, viewDidAppear, viewWillDisappear, viewDidDisappear
  • Massive View Controller — antipattern utama iOS, diselesaikan melalui MVVM atau Coordinator

Apa itu ViewController?

UIViewController — kelas dari framework UIKit yang mengelola hierarki UIView dan mengoordinasikan tampilan data di layar. Setiap aplikasi iOS berisi setidaknya satu ViewController — pengontrol akar jendela. Pengontrol menangani rotasi layar, transisi antar layar, dan peristiwa siklus hidup.

Arsitektur MVC (Model-View-Controller) di iOS diimplementasikan tepat melalui UIViewController: pengontrol menerima data dari model dan memperbarui tampilan. ViewController bukan elemen visual — ia mengelola properti view yang berisi hierarki subview. Menurut data Apple (2026), UIKit berisi lebih dari 40 subkelas UIViewController bawaan.

iPhone SDK pertama (2008) menyertakan UIViewController dengan tiga metode siklus hidup. Selama 18 tahun Apple menambahkan dukungan untuk Container View Controller, presentasi adaptif, UIViewControllerTransitioningDelegate untuk animasi kustom dan mode layar terpisah di iPad. UIViewController tetap menjadi komponen wajib untuk aplikasi UIKit.

Siklus Hidup UIViewController

Siklus hidup UIViewController — urutan metode yang dipanggil oleh sistem saat membuat, menampilkan, dan menyembunyikan layar. Memahami siklus hidup sangat penting: penempatan kode yang salah menyebabkan kebocoran memori, permintaan jaringan yang tidak perlu, dan kedipan antarmuka.

MetodeSaat dipanggilTujuan
viewDidLoadSekali, setelah view dimuat ke memoriKonfigurasi awal UI, langganan Combine
viewWillAppearSebelum layar munculPembaruan data, sembunyikan/tampilkan navigation bar
viewDidAppearSetelah layar munculMemulai animasi, analitik, pembaruan kamera
viewWillDisappearSebelum meninggalkan layarMenyimpan draf, berhenti berlangganan notifikasi
viewDidDisappearSetelah meninggalkan layarMenghentikan proses berat, membebaskan sumber daya

Urutan pemanggilan saat layar muncul

Saat pertama kali layar ditampilkan: init → loadView → viewDidLoad → viewWillAppear → viewDidAppear. Saat muncul kembali (kembali dari layar lain): viewWillAppear → viewDidAppear. viewDidLoad hanya dipanggil sekali selama masa hidup pengontrol.

viewDidLoad, init dan konfigurasi UI

Metode viewDidLoad — titik utama konfigurasi antarmuka pengguna. Dipanggil setelah view dimuat ke memori, ketika semua IBOutlet sudah terhubung. Di sini elemen UI dibuat secara terprogram, constraints dikonfigurasi, data awal dimuat.

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

Di SwiftUI kode ini setara dengan body View. Namun UIViewController memberikan kontrol penuh atas siklus hidup dan optimasi. bindViewModel menggunakan Combine untuk langganan reaktif — data diperbarui secara otomatis saat model berubah.

viewWillAppear dan pembaruan data

viewWillAppear dipanggil setiap kali sebelum layar muncul, bahkan jika sudah ada di memori. Ini adalah tempat untuk memperbarui data yang mungkin berubah di layar lain: memuat ulang daftar, memperbarui penghitung notifikasi, mengonfigurasi navigation bar untuk layar tertentu.

swift
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    // Sembunyikan navigation bar di layar ini
    navigationController?.setNavigationBarHidden(true, animated: animated)

    // Perbarui data saat kembali dari layar lain
    tableView.reloadData()
    badgeLabel.text = "\(CartManager.shared.itemCount)"
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    // Analitik: hanya setelah pengguna melihat layar
    AnalyticsService.shared.logScreenView("Profile")
}

Perbedaan antara viewDidLoad dan viewWillAppear sangat penting: viewDidLoad dijalankan sekali dan cocok untuk konfigurasi statis, viewWillAppear — setiap kali ditampilkan, cocok untuk pembaruan dinamis. Menempatkan permintaan jaringan di viewDidLoad akan menyebabkan data usang ditampilkan saat kembali ke layar.

Container View Controller: UINavigationController dan UITabBarController

Container View Controller — ViewController yang mengelola satu atau lebih ViewController anak. Apple menyediakan tiga container bawaan: UINavigationController (tumpukan layar), UITabBarController (tab), dan UISplitViewController (master-detail untuk iPad).

UINavigationController mengatur transisi dalam tumpukan — push menambahkan layar, pop menghapusnya. UITabBarController beralih antar bagian independen aplikasi. UISplitViewController menampilkan dua pengontrol berdampingan di iPad dan satu di iPhone. Pengembang dapat membuat container sendiri melalui addChild.

swift
// Container View Controller kustom
final class ContainerViewController: UIViewController {

    private let sidebarVC = SidebarViewController()
    private let contentVC = ContentViewController()

    override func viewDidLoad() {
        super.viewDidLoad()

        // Menambahkan pengontrol anak
        addChild(sidebarVC)
        view.addSubview(sidebarVC.view)
        sidebarVC.didMove(toParent: self)

        addChild(contentVC)
        view.addSubview(contentVC.view)
        contentVC.didMove(toParent: self)
    }
}

Bekerja dengan benar dengan Container View Controller memerlukan pemanggilan addChild, menambahkan view dan didMove(toParent:) dalam urutan ini. Saat menghapus — willMove(toParent: nil), removeFromSuperview, removeFromParent. Pelanggaran urutan menyebabkan kebocoran memori.

Mengatasi Massive View Controller dengan MVVM dan Coordinator

Masalah Massive View Controller — ketika UIViewController berisi ratusan baris kode dengan logika bisnis, permintaan jaringan, navigasi, dan kode UI. Apple menyadari masalah ini dan merekomendasikan MVVM (Model-View-ViewModel) bersama dengan Coordinator untuk memisahkan navigasi.

MVVM memindahkan logika bisnis dari pengontrol ke ViewModel. Controller hanya menghubungkan ViewModel dengan View melalui Combine atau delegate. Coordinator memisahkan logika navigasi — pembuatan dan transisi antar pengontrol — ke dalam kelas terpisah. Pendekatan ini telah dimasukkan ke dalam praktik terbaik Apple sejak 2024.

swift
// Coordinator — manajemen navigasi
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: kapan memilih apa

Pilihan antara UIViewController dan SwiftUI View tergantung pada tahun dimulainya proyek, persyaratan kustomisasi, dan versi iOS minimum yang didukung. UIKit dengan UIViewController tetap menjadi dasar untuk proyek yang dimulai sebelum 2020 dan untuk aplikasi dengan kustomisasi antarmuka yang mendalam.

SwiftUI cocok untuk proyek baru dengan iOS 17+, antarmuka standar, dan prototipe. Namun untuk transisi kustom, bekerja dengan kamera, MapKit, animasi CALayer kompleks diperlukan UIViewController. Apple merekomendasikan menggabungkan pendekatan melalui UIHostingController (SwiftUI di dalam UIKit) dan UIViewRepresentable (UIKit di dalam SwiftUI).

SkenarioUIKit (UIViewController)SwiftUI (View)
Animasi kustomKontrol penuh melalui UIViewPropertyAnimatorTerbatas melalui Animation
Bekerja dengan kameraAVCaptureSession + UIViewPreviewMelalui UIViewControllerRepresentable
CollectionViewUICollectionView + UICollectionViewLayoutLazyVGrid/LazyHGrid
Adaptasi iPadUISplitViewController + UITraitCollectionNavigationSplitView + sizeClass
Kecepatan pengembanganLebih lambat (layout manual)Lebih cepat (deklaratif)

Pertanyaan yang Sering Diajukan

Apa perbedaan UIViewController dengan UIView?

UIViewController — pengontrol yang mengelola layar dan siklus hidupnya. UIView — tampilan yang menampilkan konten. ViewController berisi hierarki UIView, tetapi bukan elemen visual itu sendiri. Satu pengontrol mengelola banyak tampilan.

Apa itu Massive View Controller?

Massive View Controller — antipattern ketika UIViewController berisi terlalu banyak logika: data, navigasi, permintaan jaringan, animasi. Solusi — memisahkan kode ke layanan terpisah, koordinator, dan ViewModel (MVVM).

Bagaimana cara mentransfer data antar ViewController?

Empat cara: melalui properti saat prepare(for:sender:) (Segue), melalui Delegate, melalui Closure, melalui layanan bersama. Untuk kopling longgar digunakan Coordinator + Delegate atau Combine.

Apa itu Container View Controller?

Container View Controller — pengontrol yang mengelola ViewController anak. Contoh: UINavigationController, UITabBarController, UISplitViewController. Pengontrol induk menambahkan anak melalui addChild, beralih di antara mereka, dan mengelola layout mereka.

Kapan menggunakan UIViewController daripada SwiftUI View?

UIViewController — untuk animasi kustom kompleks, bekerja dengan kamera, peta, video, UICollectionView dengan layout kustom. SwiftUI View — untuk antarmuka standar iOS 13+. Menggabungkan melalui UIHostingController diperbolehkan.

Kesimpulan

  • UIViewController — kelas sentral UIKit untuk mengelola layar, hierarki UIView, dan siklus hidup
  • Siklus hidup terdiri dari lima metode: viewDidLoad, viewWillAppear, viewDidAppear, viewWillDisappear, viewDidDisappear
  • viewDidLoad — titik konfigurasi awal UI, dipanggil sekali selama masa hidup pengontrol
  • viewWillAppear — dipanggil setiap kali sebelum ditampilkan, cocok untuk pembaruan data dan konfigurasi navigation bar
  • Container View Controller (UINavigationController, UITabBarController) mengelola hierarki pengontrol anak
  • Massive View Controller diatasi melalui MVVM (memisahkan logika ke ViewModel) dan Coordinator (memisahkan navigasi)
  • UIViewController dan SwiftUI dapat digabungkan melalui UIHostingController dan UIViewRepresentable untuk aplikasi hibrida

Kami akan mengembangkan aplikasi seluler turnkey

IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.

Diskusikan proyek

Baca juga