Search code examples
swiftuistoryboardios13uiscenedelegate

How to make Onboarding work with Scene Delegate in iOS13?


I am trying to set up my onboarding screen in the SceneDelegate.

When I run the code below, it compiles, but just goes to a black screen.

They're many great onboarding tutorials for AppDelegate, but very few for the new SceneDelegate with iOS13. I took this tutorial and tried to apply it to SceneDelegate, but I can't get it to work: https://www.youtube.com/watch?v=y6t1woVd6RQ&t=537s

This is my scene delegate code.

    var window: UIWindow?

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

        let launchedBefore = UserDefaults.standard.bool(forKey: "hasLaunched")
        self.window = UIWindow(frame: UIScreen.main.bounds)
        let launchStoryboard = UIStoryboard(name: "Onboarding", bundle: nil)
        let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
        var vc: UIViewController
        if launchedBefore
        {
            vc = mainStoryboard.instantiateInitialViewController()!
        }
        else
        {
            vc = launchStoryboard.instantiateViewController(identifier: "Onboarding")
        }
        UserDefaults.standard.set(true, forKey: "hasLaunched")
        self.window?.rootViewController = vc
        self.window?.makeKeyAndVisible()

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

I've tried it both with commenting out the last guard statement and with not commenting it out.


Solution

  • You're creating the window incorrectly, so you're going to end up with a black screen. It would be a lot better to let the storyboard create the window for you, since you don't know how to do it. Just delete this line completely:

    self.window = UIWindow(frame: UIScreen.main.bounds)
    

    You can also cut this line, as it is also otiose (the storyboard will do this for you as well):

    self.window?.makeKeyAndVisible()
    

    Your sole responsibility now is to set the value of self.window?.rootViewController. Note that you do not need to say

    vc = mainStoryboard.instantiateInitialViewController()!
    

    because that is the root view controller already, given to you by the storyboard. Thus the only thing you need to do, in the architecture you've posited, is replace the root view controller in the situation where the user needs to be onboarded.

    (See my github repo for a working example.)