0
0
iOS Swiftmobile~20 mins

Coordinator pattern in iOS Swift - Mini App: Build & Ship

Choose your learning style9 modes available
Build: MainCoordinator Example
Build a simple app using the Coordinator pattern to manage navigation between two screens: Home and Details. The Home screen has a button to go to Details. The Coordinator handles the navigation logic.
Target UI
┌─────────────────────────┐
│        Home Screen       │
│                         │
│   [Go to Details Button] │
│                         │
└─────────────────────────┘

After tapping button:

┌─────────────────────────┐
│       Details Screen     │
│                         │
│   [Back Button (NavBar)] │
│                         │
└─────────────────────────┘
Create a Coordinator protocol with start() method
Implement MainCoordinator class to manage UINavigationController
HomeViewController with a button labeled 'Go to Details'
DetailsViewController with a simple label 'Details Screen'
Navigation from Home to Details handled by MainCoordinator
Use UINavigationController for navigation stack
Back button in Details screen to return to Home
Starter Code
iOS Swift
import UIKit

protocol Coordinator {
    func start()
}

class MainCoordinator: Coordinator {
    let navigationController: UINavigationController

    init(navigationController: UINavigationController) {
        self.navigationController = navigationController
    }

    func start() {
        // TODO: Show HomeViewController
    }

    func showDetails() {
        // TODO: Show DetailsViewController
    }
}

class HomeViewController: UIViewController {
    var coordinator: MainCoordinator?

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        // TODO: Add button to go to Details
    }

    @objc func goToDetailsTapped() {
        // TODO: Notify coordinator to show details
    }
}

class DetailsViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        // TODO: Add label 'Details Screen'
    }
}

@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
    }
}
Task 1
Task 2
Task 3
Task 4
Task 5
Solution
iOS Swift
import UIKit

protocol Coordinator {
    func start()
}

class MainCoordinator: Coordinator {
    let navigationController: UINavigationController

    init(navigationController: UINavigationController) {
        self.navigationController = navigationController
    }

    func start() {
        let homeVC = HomeViewController()
        homeVC.coordinator = self
        navigationController.pushViewController(homeVC, animated: false)
    }

    func showDetails() {
        let detailsVC = DetailsViewController()
        navigationController.pushViewController(detailsVC, animated: true)
    }
}

class HomeViewController: UIViewController {
    var coordinator: MainCoordinator?

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        title = "Home"

        let button = UIButton(type: .system)
        button.setTitle("Go to Details", for: .normal)
        button.translatesAutoresizingMaskIntoConstraints = false
        button.addTarget(self, action: #selector(goToDetailsTapped), for: .touchUpInside)

        view.addSubview(button)

        NSLayoutConstraint.activate([
            button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            button.centerYAnchor.constraint(equalTo: view.centerYAnchor)
        ])
    }

    @objc func goToDetailsTapped() {
        coordinator?.showDetails()
    }
}

class DetailsViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        title = "Details"

        let label = UILabel()
        label.text = "Details Screen"
        label.font = UIFont.systemFont(ofSize: 24, weight: .medium)
        label.translatesAutoresizingMaskIntoConstraints = false

        view.addSubview(label)

        NSLayoutConstraint.activate([
            label.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            label.centerYAnchor.constraint(equalTo: view.centerYAnchor)
        ])
    }
}

@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
    }
}

This app uses the Coordinator pattern to separate navigation logic from view controllers. The MainCoordinator manages the navigation stack using a UINavigationController. It starts by showing the HomeViewController, which has a button labeled 'Go to Details'. When the button is tapped, it calls the coordinator's showDetails() method, which pushes the DetailsViewController onto the navigation stack. The back button in the navigation bar is automatically provided by UINavigationController, allowing the user to return to the Home screen. This pattern keeps view controllers simple and focused on UI, while the coordinator handles navigation flow.

Final Result
Completed Screen
┌─────────────────────────┐
│        Home Screen       │
│                         │
│   [Go to Details Button] │
│                         │
└─────────────────────────┘

User taps button ->

┌─────────────────────────┐
│       Details Screen     │
│                         │
│      Details Screen      │
│                         │
│  < Back (Nav Bar Button) │
└─────────────────────────┘
User sees Home screen with a centered button labeled 'Go to Details'.
Tapping the button navigates to Details screen with a label 'Details Screen'.
Navigation bar shows a back button to return to Home screen.
Stretch Goal
Add a third screen called About, accessible from Details screen with a button labeled 'About'. Use the coordinator to navigate to About screen.
💡 Hint
Create AboutViewController with a label. Add a method in MainCoordinator to show About screen. Add a button in DetailsViewController that calls coordinator to navigate.