Coordinators, the back button problem and a simple way to fix it

Toby O'Connell
CodeX
Published in
2 min readFeb 17, 2021

--

Background

The Coordinator pattern has become increasingly popular recently in handling navigation through an iOS apps without tightly coupling different view controllers.

There are a number of great articles that explain the various flavours of the pattern fantastically, so I’ll not rehash the same detail again.

There is, however, one area which causes problems for many of these implementations and problem is the UINavigationController’s back button.

Ideally we would have the Coordinator handle all navigation interactions directly, however the back button does not allow for its action to be modified as it is directly tied to the navigation controller.

This causes a problem when the back button is pressed on the first view controller managed by a Coordinator. If there is no handler for the button press, there is no opportunity to remove the Coordinator from its parent and thus the memory is leaked.

One great blog post on the subject by Soroush Khanlou explains two potential solutions to this problem:

  • The first is Bryan Irace’s approach. This involves implementing UINavigationControllerDelegate methods to detect a popping of a view controller, find its corresponding Coordinator and remove it if necessary.
  • The second solution mentioned is Ian MacCallum’s approach. This also utilises UINavigationControllerDelegate but wraps it up in a Router object to decouple navigation controller and Coordinator.

Unfortunately both of these solutions introduce a lot of boiler plate code to react to the back button being pressed.

Ideally, when a view controller no longer needs its Coordinator, the Coordinator would simply be deallocated.

A new solution…

One solution I have found to manage this issue is inverting the ownership of Coordinators. By allowing the view controllers to keep their Coordinator alive, when the last one view controller is removed, so is the Coordinator.

We start with a simple Coordinating protocol:

From there we can add a concrete implementation:

It’s important to note here that the first view controller has a strong reference to InitialCoordinator intentionally. This means that SceneDelegate needs no reference toInitialCoordinator, so when the view controller is deallocated, the Coordinator will be deallocated too.

To present ChildCoordinator we simply instantiate it and call its start method. This is the same as starting InitialCoordinator in SceneDelegate:

Conclusion

This solution to the problem introduces little to no boiler plate code and utilises Swift’s automatic reference counting to handle disposing of Coordinators when they are no longer needed.

A more fully fleshed out project including how to handle modal presentation can be found in the following github repo:

--

--

Toby O'Connell
CodeX

Swift / iOS developer - I write about things that I find interesting or innovative.