Contact
← Back to Topics

Coordinator Design Pattern

Pattern for managing navigation flow and decoupling view controllers in iOS apps.

About Coordinator Design Pattern

The Coordinator pattern is an architectural design pattern that manages navigation flow and handles the passing of data between view controllers. It helps to decouple view controllers from each other, making the app more maintainable and testable.

Key Features

  • Centralized navigation logic
  • View controller decoupling
  • Hierarchical coordinator structure
  • Clean passing of data
  • Improved testability

Code Example

// Coordinator pattern example
import UIKit

// Base coordinator protocol
protocol Coordinator: AnyObject {
    var childCoordinators: [Coordinator] { get set }
    var navigationController: UINavigationController { get set }
    
    func start()
}

// Main application coordinator
class AppCoordinator: Coordinator {
    var childCoordinators = [Coordinator]()
    var navigationController: UINavigationController
    
    init(navigationController: UINavigationController) {
        self.navigationController = navigationController
    }
    
    func start() {
        let vc = LoginViewController.instantiate()
        vc.coordinator = self
        navigationController.pushViewController(vc, animated: false)
    }
    
    func showMainFlow() {
        let mainCoordinator = MainCoordinator(navigationController: navigationController)
        childCoordinators.append(mainCoordinator)
        mainCoordinator.start()
    }
    
    func showProductDetails(product: Product) {
        let detailsCoordinator = ProductDetailsCoordinator(navigationController: navigationController, product: product)
        childCoordinators.append(detailsCoordinator)
        detailsCoordinator.start()
    }
    
    func childDidFinish(_ child: Coordinator?) {
        for (index, coordinator) in childCoordinators.enumerated() {
            if coordinator === child {
                childCoordinators.remove(at: index)
                break
            }
        }
    }
}

// View controller with coordinator reference
class LoginViewController: UIViewController {
    weak var coordinator: AppCoordinator?
    
    static func instantiate() -> LoginViewController {
        // Initialize from storyboard or programmatically
        return LoginViewController()
    }
    
    @IBAction func loginButtonTapped() {
        // Perform login logic
        coordinator?.showMainFlow()
    }
}