This is an exploratory blog post about coordinators. Many blog posts tend to focus on either the idea only, or specific “nice” examples where coordinators are great to use. In this post, I will go over a few crossroads I had while implementing a small app with the coordinator pattern and what I did to get over them, for better or worse.
If you have already consumed the many  blog posts and videos about coordinators, you can skip this section completely.
An issue that often comes up in apps is that a view controller is in charge of too much. One part is navigation, since view controller often are the ones that pushes other view controllers. This often means that they are dependent on each others, if we for example want to send a variable from the 1st view to the 4th, we need to either pass it through the intermediate views as well, or maybe store it as a global variable.
Here is an example, visualized.
We pass X through several screens just to finally be able to use it in the last one.
So how does a coordinator solve this? Here is how it can look.
Now the coordinator is what is actually holding all variables which are important in this specific flow, and each view controller need to care only about gathering the data and sending it back up.
Another thing to notice is that the view controllers are 100% unknown to each other, meaning we can reuse, re-order, add, remove them very easily from the coordinator layer.
Not shown in the simple example is that a coordinator can also present other coordinators so entire flows can be reused.
That was a short introduction. Read the links at  if you want more, or just Google “iOS coordinators”.
Goals with this project
Because I am building this app for scratch, I thought that I might as well set a few goals for myself while I’m at it.
UIViewControllers should strictly belong to the view layer. This means they should not contain any sort of business logic or send any requests. They should only present data, handle user input, and set themselves up.
Testable, since UIViewControllers aren’t allowed to do any sort of logic (and same goes for coordinators) it means that all data sources, models, and business logic should be encapsulated, and with that - testable.
It should be a feature-complete app, with a few common things such as web requests and data persistence. No writing complicated flows “just because”. I want to approach it as if I was building something for an App Store release, more or less.
No storyboards or XIBs. Unrelated to coordinators themselves, mainly because I’ve not done it for a full app before.
Objective C: Because as far as I’ve seen, 100% of the articles I’ve seen are in Swift.
As I am writing this near the end of the app, I think I’ve hit each goal fairly well. I’ll go over each one later in the article.
The app I’ve been building is a very simple trivia questions app. It allows you to pick a name, pick a few options, answer some questions and then see your results. Here it is in its entirety.
We can note that regardless of architecture, “good or bad”, the flow for the user would be exactly the same. Like in the image above.
Issues with “the normal way”
If we build this app “normally”, pushing the controllers from left to right, we will run into a few issues as mentioned in the previous section.
When we get to the results screen and want to return to the “options” screen we would have to go through the whole UINavigationController stack until we found an instance of that specific UIViewController, then pop to it.
When we want to go back to the start screen, we could pop to the root. However this could cause issues if we introduced another flow where the start screen wasn’t actually the root. I want to note that this was an actual bug I’ve faced in a production app.
To re-iterate the issue of passing objects through view controllers, in our case we would have to pass the name of a user throughout the whole application if we wanted to show it at the end, which we want.
So how does this app look when using coordinators then?
Trivia App with coordinators
Below we can see all screens within the app, and which flow they are presented in. We also see that the AppCoordinator is now presenting one of two possible coordinators, which in turn are then presenting the actual view controllers.
One thing I haven’t mentioned is how a view controller actually talks to its coordinator. The truth is that they actually don’t know who they are talking to at all, because each view controller has a delegate which it passes messages to. It is the coordinators themselves that implements these protocols and knows how the view controllers will act.
This brings us to another part which I was a slight bit unprepared for.
Each view controller has its own protocol, this means that if you have a view controller who’s only purpose is to let the user press “next”, you need to define a protocol where that action is exposed. The coordinator then needs to conform to it, and implement that protocol.
It will become quite delegate heavy code, since a view controller might send an action that a coordinator replies to. Then that coordinator will send some message to its delegate (which is the presenting coordinator).
To be a bit more clear, the actual map of the app looks more like this (etc).
The view controllers themselves might also have sub delegates, like UITableViewDelegate, UITableViewDataSource. However since each one is super encapsulated these ones doesn’t really matter in the grand scheme of things anyway.
Unanswered questions I had when starting
So at the start of this article I had a few questions about the whole thing. They were roughly.
Where does the web request actually sit? Because it is not really a navigation thing, but it also doesn’t fit in the view controller (since that is now strictly a view layer).
Where and when do I grab my persisted data? This is a similar question as the web requests.
How do I deal with “pickers”. A picker can be an entire navigation flow (like a full screen table view).
How do I deal with e.g. form validation, since a view controller should be strictly a view + touch-forwarding class.
Through building my app, I specifically made design decisions which would allow me to think about, and solve, these questions.
My issue: A web request is not a view layer thing, nor is it a navigation thing. So where should it be?
My solution, in short: In my case, I put it inside the coordinator. A reason was that the request is kind of related to the navigation flow, since the result of the request determines that we can start a game (or present some error).
Here is the code in the coordinator class.
And here is a visualization. I am using a completely separate view controller as a loading indicator, presented by the coordinator. Since view controller are views now, this is fine.
Another solution to presenting a loading indicator could be to keep it in the view controller as a separate state. Using a separate view controller, however, allowed me to keep the code minimal and more direct in each of them.
Persisting data (and reading the data)
My issue: Basically the same as the web request. Where do we actually load and persist data from?
My solution: For this issue, I simply created an object that does it internally, and I call it from the coordinator.
Doing it this way allows the view controller to again only be responsible for providing specific data, in my case a name.
Should I move the UserStore down into the view controller, it (the view controller) could have returned the whole User object, making the code in the coordinator lighter. However in that case, it would be more work to later add other steps, such as a profile picture or an email, into the flow. It would also pollute the view controller code a bit more in my opinion.
For a visualization of this, see the “Coordinator primer” section again, that’s basically how I ended up doing it.
My issue: Who is responsible for presenting the picker view? The coordinator or the view controller? The coordinator should do navigation, however the picking flow is internal to a specific screen.
My solution: I chose to put it in the coordinator. The things we pick are related to the flow itself (users & game options), so the delegate of the picker is also the coordinator which actually gets the data. The “presenting” view controllers actually doesn’t do anything other than act as a GUI to pass the various button taps to the coordinator.
Let’s take an example of starting a game. The coordinator will hold an object which contains multiple types of game options. Here is how it goes.
- GameCoordinator holds the game options
- Presents the game options view controller (difficulty, category and number of questions)
- The user picks one of them
- GameCoordinator prepares the correct data (e.g. data = category.allData)
- Injects the data into the PickerViewController and sets itself as its delegate
- User will pick one of the data in the picker
- Picker tells its delegate (GameCoordinator) that it picked X
- GameCoordinator adds X to its game options array
- GameCoordinator dismisses the picker
When we later gets a message from a view controller that we intend to start the game, we use the picked options to create the web request as per the web request section of this article.
It looks something like this.
Here’s the actual code that presents the picker, within the coordinator.
Here is the code that actually responds to the picker once the user have selected something, again in the coordinator.
Misc thoughts 1: We can see that I manually tell the options view controller to update its labels after we change some of the options. I guess that using MVVM with data bindings would make this unnecessary, however I have not tried this yet.
Misc thoughts 2: Despite me wanting to keep UIViewControllers as view objects only, the picker view controllers are technically datasources as they conform to UITableViewDataSource. However, since I do inject the actual data from proper models, I think that this is fine for now.
This section is going to be super short without nice images, because the solutions seems to follow a red thread. Create the object as isolated as possible for testing purposes - then inject it into the view controllers.
The form validation follows the same pattern, except that I did not yet inject it into the view controller. I would likely do that once I need to reuse the view controller with another type of validation.
I’ve never actually done proper unit testing before, except for very specific scenarios for objects that had a very complicated implementation that easily broke.
In this project, I added unit testing to all model objects and I think it can help out a lot, especially in a large project with many critical items working together. It did take another day to write the tests, so I likely won’t do it for tiny apps, but for larger ones with business value I think I will try to start doing it.
I’m not sure how (or if) to test view controllers, unless I do it with UI testing. I suppose that’s the only option? Regardless, I will investigate it and UI testing is something I am fond of nowdays either way, so it will be done.
I am definitely interested in using this pattern in a proper larger project, and I will try to do just that. For a tiny application, just a few screens worth, it might not be worth the effort.
Writing code in this way seems to help with making things testable, although as stated in the testing paragraphs, I am still not 100% comfortable with writing tests.
 See all of the below
Presenting Coordinators - Soroush Khanlou (video)
Coordinators – Soroush Khanlou (video)
An iOS Coordinator Pattern
Flow Coordinators in iOS
 This deals with a few message sending things
MVC-C, Injecting Coordinator pattering in UIKit