set initial viewcontroller in appdelegate - swift

I would like to set the initial viewcontroller from the appdelegate. I found a really good answer, however it's in Objective C and im having trouble achieving the same thing in swift.

Programmatically set the initial view controller using Storyboards

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];

    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];

    UIViewController *viewController = // determine the initial view controller here and instantiate   it with [storyboard instantiateViewControllerWithIdentifier:<storyboard id>];

    self.window.rootViewController = viewController;
    [self.window makeKeyAndVisible];

    return YES;
}

Anyone able to help?

I want the initial Viewcontroller to be dependent on certain conditions being met using a conditional statement.


Solution 1:

Xcode11 and SceneDelegate note:

Starting from Xcode11, because of SceneDelegates, it's likely that you shouldn't do it inside AppDelegate. Instead do it from SceneDelegate. For more on that see this other answer


Old answer:

I used this thread to help me convert the objective C to swift, and its working perfectly.

Instantiate and Present a viewController in Swift

Swift 2 code:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
    
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    
    let initialViewController = storyboard.instantiateViewControllerWithIdentifier("LoginSignupVC")
    
    self.window?.rootViewController = initialViewController
    self.window?.makeKeyAndVisible()
    
    return true
}

Swift 3 code:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    self.window = UIWindow(frame: UIScreen.main.bounds)

    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    
    let initialViewController = storyboard.instantiateViewController(withIdentifier: "LoginSignupVC")

    self.window?.rootViewController = initialViewController
    self.window?.makeKeyAndVisible()

    return true
}

Solution 2:

Try this. For example: You should use UINavigationController as the initial view controller. Then, you can set any view controller as root from the storyboard.

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    // Override point for customization after application launch.
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let navigationController = storyboard.instantiateInitialViewController() as UINavigationController
    let rootViewController = storyboard.instantiateViewControllerWithIdentifier("VC") as UIViewController
    navigationController.viewControllers = [rootViewController]
    self.window?.rootViewController = navigationController
    return true
}

See my storyboard screen.

Solution 3:

For new Xcode 11.xxx and Swift 5.xx, where the target it set to iOS 13+.

For the new project structure, AppDelegate does not have to do anything regarding rootViewController.

A new class is there to handle window(UIWindowScene) class -> 'SceneDelegate' file.

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?

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

    if let windowScene = scene as? UIWindowScene {
        let window = UIWindow(windowScene: windowScene)
        window.rootViewController = // Your RootViewController in here
        self.window = window
        window.makeKeyAndVisible()
    }

}

Solution 4:

Swift 3, Swift 4:

Change first line to

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool

the rest is same.

Swift 5+:

Instantiate root view controller from storyboard:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // this line is important
        self.window = UIWindow(frame: UIScreen.main.bounds)

        // In project directory storyboard looks like Main.storyboard,
        // you should use only part before ".storyboard" as its name,
        // so in this example name is "Main".
        let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
        
        // controller identifier sets up in storyboard utilities
        // panel (on the right), it is called 'Storyboard ID'
        let viewController = storyboard.instantiateViewController(withIdentifier: "YourViewControllerIdentifier") as! YourViewController

        self.window?.rootViewController = viewController
        self.window?.makeKeyAndVisible()        
        return true
    }

If you want to use UINavigationController as root:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // this line is important
        self.window = UIWindow(frame: UIScreen.main.bounds)

        let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
        let viewController = storyboard.instantiateViewController(withIdentifier: "YourViewControllerIdentifier") as! YourViewController
        let navigationController = UINavigationController.init(rootViewController: viewController)
        self.window?.rootViewController = navigationController

        self.window?.makeKeyAndVisible()        
        return true
    }

Instantiate root view controller from xib:

It is almost the same, but instead of lines

let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: "YourViewControllerIdentifier") as! YourViewController

you'll have to write

let viewController = YourViewController(nibName: "YourViewController", bundle: nil)