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()