loading...

Create a iOS app without Storyboard, since Xcode 11.0 (iOS 13+)

toni777772 profile image Anton Paliakou ・2 min read

Well, sometimes developers have a great opportunity to create projects from scratch. And after creating a project, developers are divided into 2 groups:

  1. Who preferer keep storyboard as an entry point to the application.
  2. Who preferer set rootViewController for window via code.

Consider in more detail way set rootViewController via code.

Before iOS 13 and Xcode 11

Before iOS 13 and Xcode 11 code for set rootViewController we inserted in function application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool in AppDelegate .

Example setup LoginViewController as root in AppDelegate. LoginViewController is simple child of UIViewController.

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Create a new window property 
        self.window = UIWindow(frame: UIScreen.main.bounds)

        // Set custom LoginViewController as root
        self.window?.rootViewController = LoginViewController()

        // Present the window
        self.window?.makeKeyAndVisible()
        return true
    }
}

After creating new *Single View App project since Xcode 11, this way does not work.*

Since iOS 13 and Xcode 11

So, way for set rootViewController via code after Xcode 11 and iOS 13 changed.
There are some fundamental changes to the application lifecycle with iPadOS and iOS 13. Windows are managed by a UISceneSession now. New projects have new Swift file SceneDelegate.
Also see sample app supporting multiple windows on iPad.
But this article answer another question: Where to setup rootViewController?
SceneDelegate has function scene(_ scene: UIScene,
willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions)
. The function tells the delegate about the addition of a scene to the app. This is the right place to setup!

Example setup LoginViewController as root in SceneDelegate.

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?

    func scene(_ scene: UIScene,
               willConnectTo session: UISceneSession,
               options connectionOptions: UIScene.ConnectionOptions) {
        // Get UIWindowScene
        guard let windowScene = (scene as? UIWindowScene) else {
            return
        }

        // Create a new window property 
        self.window = UIWindow(frame: windowScene.coordinateSpace.bounds)

        // Set windowScene for window
        self.window?.windowScene = windowScene 

        // Set custom LoginViewController as root
        window?.rootViewController = LoginViewController()

        // Present the window
        window?.makeKeyAndVisible()
    }
}

Source code

Thanks for reading! See you soon.

Discussion

markdown guide