Search code examples
iosswiftviewcontrollerxcode11

Second start of application only display a black view


On firstStart of the application I want the user to start at ViewController1 (VC1) and after completing the onboarding process and a button gets clicked in ViewController3 (VC3) should the first item of the Tab Bar controller be the new initial view controller.

The first launch works but when closing the app and upon reopening the app everything goes black.

When I set VC3 as the new initial viewController everything works fine.

My SceneDelegate

    var window: UIWindow?


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

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

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

    // Is it the apps first start?
    let firstView = UserDefaults.standard.string(forKey: "firstStart")
    let storyboard = UIStoryboard(name: "Main", bundle: nil)

    // Create the root view controller as needed
    guard let vc = storyboard.instantiateViewController(identifier: firstView ?? "Welcome") as? ViewController else {
        print("ViewController not found")
        return
    }

    let nc = UINavigationController(rootViewController: vc)

    // Create the window.
    let win = UIWindow(windowScene: windowScene)
    win.rootViewController = nc
    win.makeKeyAndVisible()
    window = win

} 

My button:

    @IBAction func buttonActivate(_ sender: Any) {
    // Change start View to "Home"
    UserDefaults.standard.set("Home", forKey: "firstStart")
}

I've tried with changing keys in Info.plist and read through UIApplicationSceneManifest but without any success. Tried having an additional navigation controller as tab bar controller item 2 shows but same result with a black screen.

change initial viewcontroller xcode11 swift5 screen black


Solution

  • You shouldn't try and change the window, instead change the .rootViewController.

    VC1 is the entry point in storyboard which means that the initial view controller your app starts with every time, during the "didFinishLaunchingWithOptions" in app-delegate you can ask whether the user has been promoted with the onboarding and in that case switch the rootViewController as follows:

    func showMainStoryboard() {
       let homeViewController = UIStoryboard(name: "StoryboardName", bundle: Bundle.main).instantiateInitialViewController()
       window?.rootViewController = homeViewController
    }
    

    In order for the following example to work for you, you must create a separate storyboard: 1 for the onboarding and 1 for main.

    Flow #1: The first time user installs the app he is promoted with the onboarding VC after he clicked the button on VC3 you switch the rootViewController on that event.

    Flow #2: After the user clicked the button and reentered the app he won't be promoted with the onboarding but routed to the "main" VC, a.k.a Start in your case.