iOS : Coordinator pattern in Swift
Have you ever being in a situation, where your viewControllers become so coupled and dependent to each others. And your navigation is scattered all over your code.
You also may have heard about Massive view controller issue. which is related to the fact that the view controller in MVC pattern is usually doing too much stuff, including the views setup code itself. in a way that the view controller becomes a view actually (and more …)
One of the tasks that the view controller is not supposed to be doing. is the screens navigation management and applications flow.
What is Coordinator pattern ?
Introduced to the iOS community by Soroush Khanlou at the NSSpain conference 2015. Coordinator pattern provides an encapsulations of navigation logic.
In other words : Instead of pushing and presenting your ViewControllers from other view controllers. All the screens navigation will be managed by coordinatos.
Hence view controllers will be isolated and invisible to each other, and could be reused easily.
As illustrated on the above schema. Coordinator pattern could be described by the following :
- We may have one or multiple view controllers by coordinator.
- Each coordinator displays its viewController(s) using a method generally called start.
- Each viewController has a delegate reference to its coordinator.
- Each coordinator has an array of child coordinators.
- Each child coordinator has delegate reference to its parent.
Let’s get on with the practice.
Important note : You might find that the below example slightly different from other implementations. This is how i personally use it. But the main mechanism is the same everywhere.
Here we will have two coordinators managing three view controllers to show that a coordinator could have one or more views.
Create a new single view project in swift. With three view controllers : FirstViewController, SecondViewController and ThirdViewController.
On each view controller add one button to navigate to the following view controller.
First we will create a coordinator protocol. With a child coordinators array and an init method receiving a navigation controller as parameter.
Then the first coordinator which will manage the first view Controller.
With the start method implementation, adding the first view controller into navigation controller.
The firstCoordinator has two extensions, one is used to navigate to the next viewController. the second one is to navigate back to the first coordinator.
We need to keep the child coordinator array updated with the current coordinator stack.
Then instead of creating directly the main controller in the didfinishlaunchingwithoptions method. We created the first coordinator with the main navigationController as parameter. And the start method will be in charge of displaying the first viewController.
Now in order to navigate to the next viewController. we will have to call the coordinator. represented by a FirstViewControllerDelegate.
As mentioned before. a coordinator may manage one or more viewControllers. So here the secondCoordinator will handle both the second and the third viewControllers.
First we create a custom back button calling a coordinator method navigateToFirstpage :
Important note : when switching between coordinators. the default navigation controller back button will break coordinator logic if the action is not overwritten. we should absolutely call our own back action using a coordinator method to ensure the child coordinator array s well updated
And then we an other method to go to the ThirdViewController :
And finally ThirdViewController calling its delegate (SecondCoordinator) to navigate to the FirstViewController. and here no need to overwrite navigationController back button, because it will not change the current coordinator.
And this way we can have a loop navigation : firstViewController -> secondViewController -> thirdViewController.
Here you can download the full source code project
Here we were able to navigate between controllers using coordinator layer, without having any reference of viewControllers in others. While moving the navigation logic to the coordinator.
Which will contribute in reducing the massive view controller effect.
Thank you for reading !!!