2

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.

  • 1
    You're creating the window incorrectly, so you're going to end up with a black screen. Working example here: https://github.com/mattneub/RegistrationExample/blob/master/RegistrationExample/AppDelegate.swift – matt Mar 07 '20 at 18:10

2 Answers2

2

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

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • Thank you! This worked, and I tested it by deleting and reinstalling the app and making sure the onboarding process worked as well. – Matt Manion Mar 07 '20 at 18:19
  • 1
    Cool, glad to help. I should mention that in my github example my architecture works the other way around from yours: the storyboard's initial view controller is the onboarding view controller, and the "normal" view controller is the one that we set in the scene delegate if the user _has_ onboarded already. However, it's up to you which way you want to play it. :) – matt Mar 07 '20 at 18:40
2

This was solved by matt, see his answer.

Just posting the correct code below for anyone trying to do Onboarding with storyboards in ios13.

    var window: UIWindow?

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

        let launchedBefore = UserDefaults.standard.bool(forKey: "hasLaunched")
        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: "OnboardingScene")
        }
        UserDefaults.standard.set(true, forKey: "hasLaunched")
        self.window?.rootViewController = vc
    }