The design coordinator template helps to divide responsibilities in the application flow. The logic of navigation passes from the view controller to the coordinator, and thus we gain greater control over the navigation flow.
Our coordinator is tailored to work with a redux-like one-way flow. I will show you a simple example of a coordinator as we do it and at the end of the article and I will provide you a link to the library which includes GoodCoordinator you can plug into the project via SPM.
Let's start with something simple. First we will make an enum file called Coordinator.swift which will contain an enum with actions that describe type of navigation. It should contain basic actions like push, present, dismiss, pop and the default value none.
Then we create a generic Coordinator class. This class will serve as a model for the other coordinators which will inherit from it. It will contain a navigationController that will be inserted in the constructor and it will be optional.
Then we need step and cancellables. They are part of the combine library available from iOS 13.
Step will have a property wrapper published which means that we can subscribe to it and listen for changes similar to if we used didSet closure.
We will add the navigate function to the coordinator class, which will serve as an interface for the child coordinatory, but here it will be empty and will do nothing.
Then we define the private function navigate which will perform the standard navigation actions that we defined above the navigation controller and we saved them in the class.
Finally, we will define the public function start, which will serve as an interface for child coordinators and at the same time will listen to the change of the step variable every time it is started, as I mentioned above. Since step is optional we use compactMap to take into account only non-zero values and in sink closure we call our private navigate function.
Now let's define some specific navigation actions. Create a file AppStep.swift and write 2 simple cases. Later, in this enum, it is possible to layer the structure on other coordinators, with each case representing one coordinator and the associated value of its AppSteps, but now let's define the simplest case.
Now we have successfully set up parentKoordinator but now let's use it. We will create the final class AppCoordinator, which will inherit from the Coordinator of the AppStep type, which we defined below.
In this coordinator, we define the appwindow. In most practical cases, the logic of windows is solved here because AppCoordinator usually decides whether we are on the Login window or we are already logged in and inside the app. In our case, we will use only one window into which will be automatically selected from the beginning.
We will set the window in inite. And in the start function we will create a navigation controller for it. And we'll show the window.
Now we are done with the preparation and let's do something in the navigation. We will override the navigate function and create decision logic via a switch above AppStep.
In each appstep we can run the viewController by returning the appstep with the viewcontroller as a parameter. You could also go back .none here and add another navigationController from another coordinator to the navigation controller.
Okay, and now let's try to integrate it into the app. In the Appdelegate class, we will create the appCoordinator variable and create it when turning on the app. The coordinator is then called to start and now it is enough to set the step to AppStep which is needed.
All done. We just used a coordinator pattern using combine. The coordinator is very easy to scale and is therefore suitable almost everywhere.
But let's see what it looks like when we are connecting two coordinators. Create a coordinator AboutAppCoordinator.swift
We now present this coordinator via the AppCoordinator step by replacing the content of the second step logic
All done. We have successfully gone through the process of coordinators. With this guide, you should be able to create a functional project navigation through the coordinators.
You can find the finished sample at my GitHub
You can find the GoodIOSExtensions library with GoodCoordinator at GoodRequest GitHub.