Enhancing Coordinators with Enums and Protocols

I am a huge fan of Coordinators. Not only do they help keep large projects more manageable and reduce the processing load put on ViewControllers, but they also allow for quickly setting up a project, and allow the project's view controllers and views to be used and reused very fluidly.

If you have never heard of Coordinators before, you definitely need to check out these two posts by Soroush Khanlou, The Coordinator and Coordinators Redux, before reading more of this post. I take his idea of Coordinators and modify them for the way I prefer to organize my projects in this article, and it would be a good idea to understand Coordinators first.

I am currently working on my third project to use Coordinators as the main architecture pattern, and before even creating the new project in Xcode, I thought of a way I can help myself organize and live in this project better.

Protocols

Protocols are integral to the Coordinators project structure. Protocols define delegate patterns that allow communication between children and the parents, be it communicating between a view controller and a coordinator, or child and parent coordinators.

However, protocols do not have to be limited to that one job. Instead, I am using protocols to define "base classes" for each of the different types of coordinators present in this project. I have three main types of coordinator in this project:

  1. Coordinator
  2. Navigation Coordinator
  3. Tab Bar Coordinator

The Coordinator is just a plain coordinator, with the only requirement being a start() method. Just a few of the coordinators I work with are of this type, but this is also the base for the other two coordinators.

protocol Coordinator {
    func start()
}

The Navigation Coordinator is a coordinator backed by a UINavigationController. Most of the coordinators I work with are of this type.

protocol NavigationCoordinator: Coordinator {
    var navigationController: UINavigationController
    var childViewControllers: [UIViewController]

    init(navigationController: UINavigationController)
}

The Tab Bar Coordinator is a coordinator backed by a UITabBarController. This coordinator holds onto children coordinators, and will be told when to switch between them.

protocol TabBarCoordinator: Coordinator {
    var tabBarController: UITabBarController
    var childCoordinators: [NavigationCoordinator]

    init(tabBarController: UITabBarController)
}

Using these different protocols, I am able to create "base classes" with which to base my coordinators, but without having to override variables in each of the subclasses. This also allows me to ensure that each variable and function I define as being a part of a certain coordinator type is used.

Breaking up the idea of Coordinators into different types of coordinators also helps mentally encapsulate how each coordinator should function, and where each one should be used in the project. This really helps when creating the coordinator structure of the project, which is really the skeleton of the entire project.

However, using protocols to define set "base coordinators" isn't the only thing I have done differently in this project. I have also started using enums to define namespaces for my project.

Enums

Namespaces are a feature of many of the popular languages that are around now, and they can be pretty useful. While Swift does not have namespaces directly built into the language, there is a similar and almost identical solution. Enums.

Enums can be used as a namespace in a very simple way. An enum can be defined and have no cases, but rather contain classes, structs, and other enums inside of them. An example of this is in the registration flow portion of the project I am working on currently. I have a coordinator, several view controllers, and a few smart views that are only being used in this section of the application. I can nest all of those classes into an enum called Registration. Then each time I write a new class, struct, or enum that will only be used in this portion of the application, I write it as an extension to the Registration enum.

enum Registration {}

extension Registration {
    class Step1ViewControler {
        …
    }
}

Then, any time I want to reference the Step1ViewController I just have to use dot syntax: Registration.Step1ViewController(). However, since I also embed my registration coordinator inside the Registration enum, whenever my coordinator creates a view controller it can just call it Step1ViewController(), since both the coordinator and the view controller are in the same namespace.

This also means that with two sections of the application, Registration and Home, each of their respective coordinators can both be named Coordinator. Since the coordinators are in different namespaces, there is no naming conflict. Then, when the home coordinator needs to be referenced, it will be referenced as Home.Coordinator, and registration as Registration.Coordinator.

Not only does this make the code a little prettier and easier to read, it also contains each part of the project in it's own space. Rather than lumping everything together in the same namespace, classes, structs, and enums can be sectioned off from each other, breaking the project up into manageable sections.

I have found while working on this project that these two philosophies, using protocols as base classes, and using enums as namespaces, have really helped me develop faster and smarter. Because the project is broken up into smaller sections, the project as a whole has become easier to manage and think about, since only small sections of the project need to be in mind at one time. Also, using protocols as base classes has helped keep me in check by defining set variables and functions that must be implemented in a coordinator, and if a variable or function is not present in the coordinator, it just won't compile.

Read “Getting the raw values of an enum” next

Nathan Ansel

Nathan Ansel

Nathan is an iOS Developer that has a passion for making beautiful, well developed apps. He loves Swift, fitness, and playing video games. He can be found on twitter at nathan3o4.