Creating Child Coordinators

Part of MVVM-C IOS Architecture Tutorial.

Bobby Pehtrus
5 min readJun 26, 2021

Finally, I’ve managed to release another article in medium. I really thank you for the claps and I’m surprised that I can have that many 😁. It’s been a rough month so it delays some of my articles. Hope you enjoy!

So I’ve talked about a brief introduction of MVVM + C pattern for IOS Development, you can find it here.

If you see the structure of the coordinator that I introduced, we see it has a children property inside.

protocol Coordinator {    var parentCoordinator: Coordinator? { get set }
var children: [Coordinator] { get set }
var navigationController : UINavigationController { get set }
func start()
}

What is it for?

Well it is possible to join Login, Register, Home, Profile, or any app flow inside a single coordinator. But it is going to be messy. If you want a more tidier coordinator, we should split some of the functionalities between coordinators. One responsible for login, one responsible for buying products, or responsible for handling home navigations. Having many child with more specific functionalities make an app easier to maintain and improve.

Creating a Child Coordinator

Let’s assume that you want to separate authentication such as Login and Register functionalities into a different coordinator. Let’s create the AuthCoordinator.

class AuthCoordinator : Coordinator {
var parentCoordinator: Coordinator?
var children: [Coordinator] = []
var navigationController: UINavigationController
init(navigationController : UINavigationController) {
self.navigationController = navigationController
}
func start() {// Setup initial VC here!}
}

In AppCoordinator, don’t forget to create and add the AuthCoordinator to the AppCoordinator’s children and assign the parent.

func goToAuth(){
// Create the coordinator
let authCoordinator = AuthCoordinator.init(navigationController: navigationController)
// Set the parent
authCoordinator.parentCoordinator = self
// Add to AppCoordinator's Child
children.append(authCoordinator)
// Do not forget to kickstart it!
authCoordinator.start()
}

Now, your Child Coordinator is born!.

You can see the full extend of the auth coordinator capability here!

When the Auth Coordinator being start, the Login Page is shown. The coordinator also manages all the login and register view dependencies.

Tab bars and Coordinator

The concept is not that complex. Usually, tabbars have many active child coordinators at the same time. The relationship between the parent has many ways.

Some prefers the left side others may choose right side. It depends on the needs of your project and your code style. Well, I often use the left side because I want to switch modules simpler like from Home to Auth, or Profile to Auth. SO, I only use the HomeTabbarCoordinator to instantiate every tabbed coordinators. Check the code down below!

You can see that I don’t assign the HomeTabbarCoordinator as the child’s parent. Why? so when a child wants to access the AppCoordinator, it can directly access it without any extra code inside HomeTabbarCoordinator.

Well you can use the right side as well, suit yourself based on your projects need.

To use the Coordinator just simply calls the function below in the AppCoordinator.

func goToHome(){
// Initiate HomeTabBar Coordinator
let coordinator = HomeTabBarCoordinator.init(navigationController: navigationController)
children.removeAll()
coordinator.parentCoordinator = self
coordinator.start()
}

Subflows

Let’s say that you have an app that does transaction. The transaction flow is huge and repetitive. And you want to make a reusable coordinator with it. Yes you can!

Transaction Example

Let say you have this very simple UI that only does switch page. And you want to modularize the Transaction Flow like below!

Transaction Flow

First, you have to create the TransactionCoordinator for that.

Then you create the TransactionViewModel.

Remember to implement the NavigationProtocol so your coordinator can implement the navigation!

Then you all set! Remember every time you want to use the flow, just create TransactionCoordinator and run start(). Remember to add the ViewModel dependencies and connect the ViewControllers to their ViewModel as well!. In this example I use a single view model for all the related flows.

⚠️ BEWARE OF MEMORY LEAKS ⚠️

Add this extension to your Coordinator so it become like this!

If you notice the childDidFinish on the goBackToHome in the Coordinator. What does it do? It is a clean up method. Did you remember that you append the child coordinator inside the parent coordinator’s children?. Yep it has to be cleaned up so the ARC can free the memory of unused coordinators. If you don’t call this in the end of the coordinator usage, then you will have a memory leak!

Remember to plan out your coordinators, their scope, their functions, even their lifecycles. When they end, when they have to stay alive!. It can saves you a lot from memory leaks.

Result

Here’s the result of the usage of Child Coordinators!

The use of child coordinators!

You can look deeper into it by dive in from my Github page here!

Conclusion

Having kids sure is a blessing. Especially they can be an expert on somethings. But having too many will make it harder for you to give them proper attentions. Same with child coordinators! They can help you manage features and modularize a whole flow. But when it is too many and too complex, it will be harder to maintain and it is prone to produce memory leaks!

But some folks tackled the memory leaks by using inverse reference coordinator pattern 😲😲. I’ve never used it before but sure interesting to look into it.

Drop some response! I will look into any useful inputs and questions when I’m free!

Wish you all good health and a good food! 🍫🍲

--

--

Bobby Pehtrus

Nomad Developer, Loves to travel and would walk for a coffee.