Coordinator Pattern for iOS

Kaninchen jäger
3 min readAug 30, 2018

--

Coordinator, or sometimes known as flow manager is a solution to a common problem when a view controller has to decide what to push or present for the next screen. To have a more clear picture of this common problem, we know:

  • UIViewControllers shouldn’t present other UIViewControllers. The only responsibilities a view controller should have are presenting data, and capturing the events.
  • There should be a separate component responsible for handling the presentation views. It looks after the flow logic, and removes that responsibility from the view controllers

In other words if you have this piece of code (or something similar) somewhere in your view controller, you probably need to consider using this pattern.

self.navigationController?.pushViewController(someViewController, animated: true)

View controllers will get tightly coupled when the view controllers themselves decide the next view controller to push into self.navigationController. With this approach the codebase will be hard to change and maintain, and the view controllers are almost impossible to reuse.

Coordinator can easily solve this problem

Coordinator is responsible for managing a group of view controllers, and it will take care of the flow logic (flow is a group of screens with similar purpose e.g. registration). It handles navigation flow, and responsible for creating and configure view controllers.

The main advantage of using coordinators is that it helps us to remove this responsibility from the view controllers. This is more elegant and clean way to handle the presentation of UIViewControllers. The Coordinator is in charge of creating the navigation controller and any of the child view controllers. The view controllers then are completely independent and have no knowledge of the context in which they are used, improving their reusability & testing.

Show me some code

Coordinator Protocol:
All Coordinators have to conform to a protocol:

protocol Coordinator: class {
func start()
}

This let us separate the coordinator’s initialization from starting its work. It help us create it however we want, and only start it when we’re ready.

public class AuthCoordinator: Coordinator {
private let navigationController: UINavigationController

public init(navigationController: UINavigationController) {
self.navigationController = navigationController
}
public func start() {
if login {
showDashboard()
} else {
showAuthentication()
}
}
private func showDashboard() {
let dashboardViewController = DashboardViewController()
dashboardViewController.delegate = self
self.navigationController.setViewControllers([dashboardViewController], animated: true)
}
private func showAuthentication() {
let loginViewController = LoginViewController()
loginViewController.delegate = self
self.navigationController.setViewControllers([loginViewController], animated: true)
}
}

So you just saw how easy you can make a coordinator for your app. Soroush made a great introduction of this pattern for iOS platform. Here is a paragraph from his blog post:

Ultimately, coordinators are just an organizational pattern. There’s no library you can use for coordinators because they’re so simple. There’s no pod you can install and nothing to subclass from. There’s not even really a protocol to conform to. Rather than being a weakness, this is a strength of using a pattern like coordinators: it’s just your code, with no dependencies.

Coordinators are very easy to use and implement, they can have huge impact on cleaning the code base and make the view controllers more loosely couple from each other.

--

--