Coordinator iOS Jul 12 2019
I am using the coordinator pattern on my Counter App. These are the steps to implement the coordinator pattern.
Table of Contents
1. Create a Coordinator
protocol.
1
2
3
4
5
6
7
import UIKit
protocol Coordinator {
var navigationController: UINavigationController { get set }
func start()
}
2. Create a class that implements the Protocol
I normally use AppCoordinator.swift
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import UIKit
class AppCoordinator: Coordinator {
var navigationController: UINavigationController
init(navigationController: UINavigationController) {
self.navigationController = navigationController
}
func start() {
let vc = DashboardViewController.instantiate()
vc.coordinator = self
navigationController.pushViewController(vc, animated: false)
}
}
The start
function is where it'll initialize our "root" controller. For this case, I'm initializing the DashboardViewController
. I'm using a modified version of a Protocol by [Paul Hudson]https://www.hackingwithswift.com/about) called Storyboarded
. Storyboarded simplifies the instantiation of specific ViewControllers (you should add an Identifier
in the Attributes inspector
on the Storyboard for your UIViewControllers
for it to work).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Storyboarded.swift
import UIKit
protocol Storyboarded {
static func instantiate(storyboard: String) -> Self
}
extension Storyboarded where Self: UIViewController {
static func instantiate(storyboard storyboardName: String = "Main") -> Self {
let fullName = NSStringFromClass(self)
let className = fullName.components(separatedBy: ".")[1]
let storyboard = UIStoryboard(name: storyboardName, bundle: Bundle.main)
return storyboard.instantiateViewController(withIdentifier: className) as! Self
}
}
All my Controllers
implement the Storyboarded
protocol and have an instance of coordinator
. My controllers communicate with the coordinator about any event that changes the flow of the App. The coordinator is responsible for handling the workflow of the App, deciding whom to call and instantiate.
3. Initialize the Coordinator in AppDelegate
Now we have to tell the AppDelegate that when the application loads initialize the coordinator so, it can start "coordinating".
The AppDelegate.swift
handles all the lifecycle of the app(going to background, initializing, being dismissed, etcetera). Inside didFinishLaunchingWithOptions
, we initialize the coordinator.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//AppDelegate.swift
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var coordinator: AppCoordinator?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let navController = UINavigationController()
coordinator = AppCoordinator(navigationController: navController)
coordinator?.start()
window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = navController
window?.makeKeyAndVisible()
return true
}
}
Usually, the App does all the window creation and presentation, but because we are taking control of the boot of the App, we have to do that too. That is why we create the window
, assign the rootViewController
and make it visible.
That's it.
References and resources
- http://khanlou.com/2015/01/the-coordinator/
- https://www.hackingwithswift.com/articles/71/how-to-use-the-coordinator-pattern-in-ios-apps
- https://www.hackingwithswift.com/articles/175/advanced-coordinator-pattern-tutorial-ios