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 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 — 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.
| Metode | Saat dipanggil | Tujuan |
|---|---|---|
| viewDidLoad | Sekali, setelah view dimuat ke memori | Konfigurasi awal UI, langganan Combine |
| viewWillAppear | Sebelum layar muncul | Pembaruan data, sembunyikan/tampilkan navigation bar |
| viewDidAppear | Setelah layar muncul | Memulai animasi, analitik, pembaruan kamera |
| viewWillDisappear | Sebelum meninggalkan layar | Menyimpan draf, berhenti berlangganan notifikasi |
| viewDidDisappear | Setelah meninggalkan layar | Menghentikan proses berat, membebaskan sumber daya |
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.
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.
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 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.
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 — 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.
// 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.
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.
// 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)
}
}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).
| Skenario | UIKit (UIViewController) | SwiftUI (View) |
|---|---|---|
| Animasi kustom | Kontrol penuh melalui UIViewPropertyAnimator | Terbatas melalui Animation |
| Bekerja dengan kamera | AVCaptureSession + UIViewPreview | Melalui UIViewControllerRepresentable |
| CollectionView | UICollectionView + UICollectionViewLayout | LazyVGrid/LazyHGrid |
| Adaptasi iPad | UISplitViewController + UITraitCollection | NavigationSplitView + sizeClass |
| Kecepatan pengembangan | Lebih lambat (layout manual) | Lebih cepat (deklaratif) |
Pertanyaan yang Sering Diajukan
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.
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).
Empat cara: melalui properti saat prepare(for:sender:) (Segue), melalui Delegate, melalui Closure, melalui layanan bersama. Untuk kopling longgar digunakan Coordinator + Delegate atau Combine.
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.
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
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.
Baca juga