Coordinator pattern with Tab Bar Controller

Vitalii Zaitcev
3 min readJul 2, 2020

What is Coordinator pattern?

Coordinator pattern is the pattern in iOS responsible for the app flows control and navigation between ViewControllers. It helps to make navigation flows more manageable and more reusable, while also letting us adjust them whenever we need.

In this article, we will figure out how we can do it using most common flows: Login flow and Main Flow (which includes Tab Bar Controller).

How does Coordinator protocol look like?

This implementation has differences from the classic one. That’s because each property and function has its own purpose which helps to build more complex and manageable apps. I tried to leave a comment above each function and property to explain what it’s for.

How do we use it?

Every app should have one main coordinator (start point of all flows) — AppCoordinator. I extended the base Coordinator protocol with additional functions to define which flows can be started from here.

The best place to initialize AppCoordinator is in the AppDelegate class.

Let’s set up the first flow:

Usually, the app starts with a Login flow where users need to sign in or sign up using their credentials. I let myself only to add a “Login button” and to leave the rest on you :)

Here is my LoginViewController:

In my previous article, I covered how do I use enums to cover view’s events.

Now we have a LoginViewController and it’s time to build LoginCoordinator responsible for login flow.

Simple as is. When user taps “Login button”, coordinator receives this event and calls “finish function”. If you go back to the definition of Coordinator protocol between 20–25 lines you’ll see what happens when this function is called. Basically it notifies, whoever is “finishDelegate”, flow is finished. Depending on logic you’re trying to achieve you need to set what is going to happen next.

Time to define Main Flow:

Now the most interesting part of this article: How do we set “Main flow” with TabBarController? I named my main coordinator “TabCoordiantor”.
Usually, I start with defining what tabs do I want to see attached to TabBarController. To do that I like to use Enums.

The nicest thing about this implementation I can change icons, names, order, etc very easily. Everything is in one place wrapped with enums. If I would want to add or remove a page, XCode will highlight the places I need to take care of.

The next part is TabBarCoordinator.

ReadyViewController, SteadyViewController, and GoViewController are basically the same as LoginViewController: one button and one callback (closure).

TabCoordinator prepares dependent ViewControllers, Tabs and initializes TabBarViewController. When “start()” function is called, it start all chain of action and runs the flow.

It’s not necessary but I added some helper functions to be able to control TabBarControtroller from TabCoordinator: change selected tab, get selected tab value, delegate callback.

Wrapping up!

Now we have LoginCoordinator and TabCoordinator ready to use. Let’s add some code to AppCoordinator to make flows work! First, we need to handle empty functions we left before:

After that, we need to go a little bit down and take care of the child coordinator delegate method and add coordination of flows:

When the child Coordinator is about to be deallocated we can check the type of its flow and decide what should be shown next. If it was Login show Main (TabBarController) flow and vice versa. The logic here can vary on the purpose of your app.

Build and Run to make it fun!

As you can see in the log window, when you switch from one coordinator to another, the first one is immediately becomes deallocated including ViewControllers it owns.

That’s it. Using coordinators we could define app flows and control navigation between ViewController. Let me know if you have any questions in the comments below. Thanks for reading!

--

--