Modul Navigasi Menggunakan Flow Controller (Coordinator)
🧩 Kenapa Butuh Flow Controller?
Biasanya, ViewController langsung memanggil pushViewController atau
present untuk pindah ke layar lain. Tapi itu bikin:
ViewController jadi gemuk dan punya tanggung jawab ganda
Sulit di-reuse dan di-test
Navigasi jadi berantakan di project besar
💡 Solusinya: Flow Controller! Alias objek terpisah yang ngurus navigasi.
🎯 1. Konsep Dasar
ViewController: cuma ngurus tampilan dan logika UI.
Coordinator / FlowController: ngatur alur pindah-pindah layar.
Struktur Umum:
AppCoordinator → root coordinator yang mulai semuanya
Setiap fitur bisa punya child coordinator sendiri (misal:
LoginCoordinator, ProfileCoordinator)
📁 Struktur Folder (simpel)
📦 App
┣ 📁 Coordinator
┃ ┣ [Link]
┃ ┗ [Link]
┣ 📁 ViewControllers
┃ ┣ [Link]
┃ ┗ [Link]
🔧 2. Protocol Coordinator
Bikin protokol dasar koordinasi:
protocol Coordinator {
var navigationController: UINavigationController { get set }
func start()
}
🚀 3. AppCoordinator: Koordinator utama
class AppCoordinator: Coordinator {
var navigationController: UINavigationController
init(navigationController: UINavigationController) {
[Link] = navigationController
}
func start() {
let homeCoordinator = HomeCoordinator(navigationController:
navigationController)
[Link]()
}
}
🏠 4. HomeCoordinator: Koordinator untuk halaman Home
class HomeCoordinator: Coordinator {
var navigationController: UINavigationController
init(navigationController: UINavigationController) {
[Link] = navigationController
}
func start() {
let vc = HomeViewController()
[Link] = { [weak self] in
self?.goToDetail()
}
[Link](vc, animated: true)
}
func goToDetail() {
let detailVC = DetailViewController()
[Link](detailVC, animated: true)
}
}
🧪 5. [Link]
class HomeViewController: UIViewController {
var onTapDetail: (() -> Void)?
override func viewDidLoad() {
[Link]()
[Link] = .systemBackground
title = "Home"
let button = UIButton(type: .system)
[Link]("Lihat Detail", for: .normal)
[Link](self, action: #selector(buttonTapped),
for: .touchUpInside)
[Link] = CGRect(x: 100, y: 200, width: 200, height: 44)
[Link](button)
}
@objc func buttonTapped() {
onTapDetail?()
}
}
📱 6. Setup di SceneDelegate (atau AppDelegate)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
var appCoordinator: AppCoordinator?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options
connectionOptions: [Link]) {
guard let windowScene = (scene as? UIWindowScene) else { return }
let nav = UINavigationController()
appCoordinator = AppCoordinator(navigationController: nav)
appCoordinator?.start()
window = UIWindow(windowScene: windowScene)
window?.rootViewController = nav
window?.makeKeyAndVisible()
}
}
🎯 Kelebihan Pakai Coordinator:
✅ Navigasi bisa diatur dari luar VC
✅ ViewController lebih bersih, lebih fokus
✅ Lebih mudah di-test
✅ Cocok untuk aplikasi besar dan kompleks
💬 Penutup
FlowController itu kayak “sutradara” yang ngatur kapan dan bagaimana
layar-layar ditampilkan. ViewController cukup jadi aktor yang fokus sama
tampilannya aja 😎