This article is about iOS Development and features examples using MVVM and Reactive Programming (ReactiveKit).

The Coordinator pattern was first introduced by Soroush Khanlou at NSSpain ‘15. In the next few paragraphs you will find out how to incorporate it into your app as the missing piece of the MVVM pattern.

MVVM and its shortcoming

Model-View-ViewModel is a commonly used and well-known architectural pattern in the iOS world, offering you a handy toolkit to build decoupled, well-structured code.

If you are not familiar with it, you can watch Ray Wenderlich’s walkthrough.

You’ve most certainly read a thousand times about the Massive View Controller and how MVVM solves that problem. However, the latter isn’t perfect in every case either.

The Problem

So what’s the issue? To put in fewest words possible: Segues force view controllers to be dependent on each other.

Let’s take a look at a simple example.

This is a fairly simple Login flow that allows you to enter your credentials or have a look at what the app has to offer first, via the Onboarding screen. Let’s say further down the road you decide to have a similar screen that will act as a walkthrough for a new feature you’ve just introduced. In the current implementation, the OnboardingViewController is tightly coupled with the LoginViewController and it is only supposed to be invoked by a segue.

The solution

First of all, it’s a good idea to stop using storyboard segues for screens that you would want to be reusable. Or just don’t use storyboard segues at all. You can either write all your view controllers programmatically, or make separate storyboards for every user story / screen.

With that being said and done ..

Enter: The Coordinator

The almighty Coordinator steps in to take the sole responsibility of navigation flow, so that your view controllers are no longer bothered by it.

Whenever there’s a need to transition to the next screen, the corresponding coordinator is notified by the viewModel.

Let’s build that Coordinator.

Coordinator Protocol

The protocol is straight-forward. Every Coordinator must have a context in which it operates on and a navigationController that it will use to present the view controllers. The push(_:) and present(_:) are just helper methods - we also provide a default implementation of those.

The start() method is intended to be used as a point of initiation of the flow.

Overview

Nothing interesting here. Let’s jump straight into the OverviewCoordinator .

Overview Coordinator

⚠️ In order for instantiateViewController(withIdentifier:) to work properly, you must specify Storyboard ID for every view controller in a storyboard. ⚠️

We already see how the issue from earlier is resolved. The OnboardingViewController/TutorialViewController that was previously married to the LoginViewController is nicely isolated and fully reusable. A strong and independent view controller.

Showing Details Screen

Let’s go back to the Overview Screen and see how we will handle tapping on a certain item and going into the Details Screen.

Step 0: tableView(_:didSelectRowAt:) :

Step 1: Bind

⚠️ If you are not using ReactiveKit / RxSwift, you can use the Delegate pattern to notify the Coordinator when it should show a screen. ⚠️

Pretty simple, right?

Coordinate the Coordinator

The concept behind coordinators should be pretty clear by now. One of the things you may still wonder about is who takes care of the coordinators? Well.. other coordinators.

App Coordinator

If you want to fully take advantage of the pattern, you have to use it all over the application you’re building.

The App Coordinator manages the intial flow and gets initiated within the App Delegate.

Declaration

Usage in AppDelegate

And that’s pretty much the foundation of it.

Conclusion

A Coordinator is an object that:

Manages the flow of the app / particular user story.

Creates View Controllers and presents them.

Creates child Coordinators and starts them.

Fully customizable to fit the requirements of the app.

—

The Coordinator pattern allows you to isolate your View Controllers so that they are highly reusable and decoupled. It makes it a thousand times easier to navigate to the same controller from multiple places or even start your app flow from a diffent screen (in case it was opened from a Quick Action, Deep Link, Notification, etc.). You are also forced to better structure your code and ditch enormous storyboards. As a result you get highly scalable, easily maintainable project.

Here you can watch the NSSpain ’15 talk where the Coordinator concept was originally introduced.

— Thank you for reading this post. ✌️