Create a iOS app without Storyboard, since Xcode 11.0 (iOS 13+)
Tags: ios, swift
Published: 2020-06-17 10:52:52

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``](https://developer.apple.com/documentation/uikit/uiwindow/1621581-rootviewcontroller) for [``window``](https://developer.apple.com/documentation/uikit/uiwindow) via code.

Consider in more detail way set [``rootViewController``](https://developer.apple.com/documentation/uikit/uiwindow/1621581-rootviewcontroller) via code.

### Before iOS 13 and Xcode 11

Before iOS 13 and Xcode 11 code for set [``rootViewController``](https://developer.apple.com/documentation/uikit/uiwindow/1621581-rootviewcontroller) we inserted in *function* [``application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool``](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623032-application) in  ``AppDelegate`` .

Example setup [``LoginViewController``](https://github.com/ToniSamples/AppWithoutStoryboard/blob/master/AppWithoutStoryboard/LoginViewController.swift) as root in ``AppDelegate``. [``LoginViewController``](https://github.com/ToniSamples/AppWithoutStoryboard/blob/master/AppWithoutStoryboard/LoginViewController.swift) is simple child of [``UIViewController``](https://developer.apple.com/documentation/uikit/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``](https://developer.apple.com/documentation/uikit/uiwindow/1621581-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``](https://developer.apple.com/documentation/uikit/uiscenesession) now. New projects have new *Swift* file [``SceneDelegate``](https://developer.apple.com/documentation/uikit/uiscenedelegate). 
Also see sample app [supporting multiple windows on iPad](https://developer.apple.com/documentation/uikit/uiscenedelegate/supporting_multiple_windows_on_ipad).
But this article answer another question:  *Where to setup rootViewController?*
[``SceneDelegate``](https://developer.apple.com/documentation/uikit/uiscenedelegate) has *function* [``scene(_ scene: UIScene, 
willConnectTo session: UISceneSession, 
options connectionOptions: UIScene.ConnectionOptions)``](https://developer.apple.com/documentation/uikit/uiscenedelegate/3197914-scene). The *function* tells the delegate about the addition of a scene to the app. This is the right place to setup!

Example setup [``LoginViewController``](https://github.com/ToniSamples/AppWithoutStoryboard/blob/master/AppWithoutStoryboard/LoginViewController.swift) 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](https://github.com/ToniSamples/AppWithoutStoryboard)

Thanks for reading! See you soon.