0
0
iOS Swiftmobile~5 mins

Coordinator pattern in iOS Swift

Choose your learning style9 modes available
Introduction

The Coordinator pattern helps organize navigation in an app. It keeps screens and navigation logic separate for easier management.

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.