The Coordinator pattern helps organize navigation in an app. It keeps screens and navigation logic separate for easier management.
0
0
Coordinator pattern in iOS Swift
Introduction
When your app has many screens and complex navigation.
When you want to avoid putting navigation code inside view controllers.
When you want to reuse navigation flows in different parts of your app.
When you want to make your app easier to test and maintain.
Syntax
iOS Swift
protocol Coordinator {
var childCoordinators: [Coordinator] { get set }
var navigationController: UINavigationController { get set }
func start()
}The Coordinator protocol defines a basic structure for coordinators.
The start() method begins the navigation flow.
Examples
This example shows a simple coordinator that starts by pushing a view controller.
iOS Swift
class MainCoordinator: Coordinator {
var childCoordinators = [Coordinator]()
var navigationController: UINavigationController
init(navigationController: UINavigationController) {
self.navigationController = navigationController
}
func start() {
let vc = ViewController()
vc.coordinator = self
navigationController.pushViewController(vc, animated: true)
}
}This method shows how to start a child coordinator for a detail screen.
iOS Swift
func showDetail() {
let detailCoordinator = DetailCoordinator(navigationController: navigationController)
childCoordinators.append(detailCoordinator)
detailCoordinator.start()
}Sample App
This app uses the Coordinator pattern to manage navigation. The MainCoordinator starts with a home screen that has a button. When tapped, it navigates to a detail screen.
iOS Swift
import UIKit protocol Coordinator { var childCoordinators: [Coordinator] { get set } var navigationController: UINavigationController { get set } func start() } class MainCoordinator: Coordinator { var childCoordinators = [Coordinator]() var navigationController: UINavigationController init(navigationController: UINavigationController) { self.navigationController = navigationController } func start() { let vc = ViewController() vc.coordinator = self navigationController.pushViewController(vc, animated: true) } func showDetail() { let detailVC = DetailViewController() navigationController.pushViewController(detailVC, animated: true) } } class ViewController: UIViewController { weak var coordinator: MainCoordinator? override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .white title = "Home" let button = UIButton(type: .system) button.setTitle("Go to Detail", for: .normal) button.addTarget(self, action: #selector(goToDetail), for: .touchUpInside) button.frame = CGRect(x: 100, y: 200, width: 150, height: 50) view.addSubview(button) } @objc func goToDetail() { coordinator?.showDetail() } } class DetailViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .lightGray title = "Detail" } } @main class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? var coordinator: MainCoordinator? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { let navController = UINavigationController() coordinator = MainCoordinator(navigationController: navController) coordinator?.start() window = UIWindow(frame: UIScreen.main.bounds) window?.rootViewController = navController window?.makeKeyAndVisible() return true } }
OutputSuccess
Important Notes
Keep coordinators focused on navigation only, not UI details.
Use child coordinators to handle complex flows inside your app.
Make sure to keep references to child coordinators to avoid them being deallocated too soon.
Summary
The Coordinator pattern separates navigation from view controllers.
It makes your app easier to manage and test.
Use coordinators to start and control screen flows.