Getting SceneDelegate to launch MainCoordinator

Getting SceneDelegate to launch MainCoordinator

·

2 min read

Summary

iOS 13+ apps that have SceneDelegate.swift require some additional work to get a MainCoordinator up and running.

Aside: Why are Coordinators awesome? Hacking With Swift makes the case for using Coordinators within the first 5 minutes of his video How to use the Coordinator pattern in iOS

Dude, where's my window?

I started with Hacking With Swift's tutorial and ran into a problem when it came time to set the window property in AppDelegate.swift.

In iOS 13, Apple introduced SceneDelegate.swift to offload the burden placed on AppDelegate in order to handle multiple windows of the same app. The best example of this is Safari. A user can launch multiple instances of Safari, similar to how they might launch multiple browser windows on a desktop computer. Each iOS Safari window has its own set of tabs. On iPad, you can place 2 Safari windows side by side.

Solution in 3 points

The key is the boiler plate code provided to you in the guard statement of willConnectTo (Thanks, Mark Struzinski!):

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

    guard let _ = (scene as? UIWindowScene) else { return }

Notice that scene is being cast from a UIScene to a UIWindowScene.

Understanding these 3 points helped me finally get my MainCoordinator to work.

// 1. Set the name of the constant of the UIWindowScene
guard let windowScene = (scene as? UIWindowScene) else { return }

let navController = UINavigationController()
coordinator = MainCoordinator(navigationController: navController)
coordinator?.start()

// 2. Instantiate a `UIWindow` using the *frame of the UIWindowScene* in step 1. This `UIWindow` will be assigned to the `window` property.
window = UIWindow(frame: windowScene.coordinateSpace.bounds)

// 3. Set `window.windowScene` to UIWindowScene in step 1.
window?.windowScene = windowScene

window?.rootViewController = navController
window?.makeKeyAndVisible()