262

How do I programmatically set the InitialViewController for a Storyboard? I want to open my storyboard to a different view depending on some condition which may vary from launch to launch.

Cœur
  • 32,421
  • 21
  • 173
  • 232
UserDev
  • 2,815
  • 3
  • 13
  • 23
  • 1
    Check [this answer](http://stackoverflow.com/a/36158926/1223728) without warning, without clearing Main storyboard in settings. – Borzh Mar 22 '16 at 15:47

23 Answers23

474

How to without a dummy initial view controller

Ensure all initial view controllers have a Storyboard ID.

In the storyboard, uncheck the "Is initial View Controller" attribute from the first view controller.

If you run your app at this point you'll read:

Failed to instantiate the default view controller for UIMainStoryboardFile 'MainStoryboard' - perhaps the designated entry point is not set?

And you'll notice that your window property in the app delegate is now nil.

In the app's setting, go to your target and the Info tab. There clear the value of Main storyboard file base name. On the General tab, clear the value for Main Interface. This will remove the warning.

Create the window and desired initial view controller in the app delegate's application:didFinishLaunchingWithOptions: method:

- (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;
}
Stan James
  • 2,277
  • 26
  • 35
Travis
  • 6,134
  • 3
  • 15
  • 14
  • 7
    Love! Love! Love! I will use this to switch between two completely different view controller trees for IOS6 and IOS7. Seems like the best way to handle backwards compatilibity, while still using all the bells and whistles in IOS7. – Hunkpapa Aug 29 '13 at 07:35
  • 6
    I am learning iOS programming in Swift. Can anyone help me how to write the above code in swift. please help. Thanks. – Raghavendra Aug 11 '14 at 07:31
  • Anyone who can answer why this is done in the `didFinishLaunchingWithOptions` method? I need to switch between onboarding/regular app and `didFinishLaunchingWithOptions` is only called when you install the app. – bdv Sep 27 '14 at 17:05
  • 1
    @bdv `didFinishLaunchingWithOptions` is called when the app is started in a new process. If you go to the home screen and return to the app, this method will not be invoked again. (Unless iOS terminates due to memory constraints.) Try stopping the app and launch once again from your IDE. If problem continues, post the issue to SO and I'll be happy to help, friend. – Travis Sep 30 '14 at 04:47
  • you don't need to initialize the window, it's already initialized. – Peyman Jan 07 '15 at 22:05
  • 2
    @peyman According to my investigation the window doesn't exist once the reference to the main storyboard is removed. I commented out the window instantiation in my current project and found this to still be the case. – Travis Jan 07 '15 at 22:49
  • I'm using this (well, a Swift version of it) and it's working well. However, I still get the "Failed to instantiate the default view controller for UIMainStoryboardFile 'Main' - perhaps the designated entry point is not set?" warning in the debug output. The app still runs fine. Is there a way to get rid of the warning? Do you get this warning? I put in a breakpoint and see that it has already appeared in the debug output before the didFinishLaunchingWithOptions code is hit. – stone Jan 27 '15 at 07:34
  • @skypecakes the same with me. Did you manage to remove the warning? – Nuno Gonçalves Mar 24 '15 at 11:53
  • 1
    @NunoGonçalves, I did get rid of the warning by setting an initial ViewController. It never actually gets loaded (breakpoint in viewDidLoad() never gets hit) unless my code in didFinishLaunchingWithOptions instantiates it, so this appears to be a fine solution. – stone Mar 24 '15 at 22:54
  • But how to set Identifier of UIViewController? – LKM Jun 01 '15 at 06:23
  • @LKM In Xcode 6.3.2, select the view controller in the Interface Builder, then in View>Utilities>Identity Inspector under 'Identity', set the 'Storyboard ID' to something useful. – Corwin Newall Jun 18 '15 at 23:34
  • 2
    @Raghav, here's the swift code: `self.window = UIWindow(frame: UIScreen.mainScreen().bounds) var storyboard = UIStoryboard(name: "Main", bundle: nil) var viewController: UIViewController = // self.window!.rootViewController = viewController self.window!.makeKeyAndVisible()` – mjmayank Jul 10 '15 at 02:24
  • 1
    I guess this can also be used to choose between (say) two different storyboards at launch time. One question is: If I intend to support State Preservation / State Restoration, perhaps I should move all that code to `application:willFinishLaunchingWithOptions:`? – Nicolas Miari Sep 08 '15 at 08:19
  • 1
    This will officially now be my default way of handling the "Login Conundrum" with UIStoryboards. It totally solved a _very_ strange problem I was having with disappearing UIBarButtonItems, but that was because I was using a methodology that just felt really not-right to me (i.e. setting the viewControllers array in the navigation controller to replace its root view controller later in the sign-in view controller. bleh.). – Evan K. Stone Jan 12 '16 at 16:20
  • Can you please check my question? http://stackoverflow.com/questions/36767816/why-not-just-set-initial-view-controller-for-login-screen-like-this – osrl Apr 21 '16 at 11:13
  • **1)** What happens if you don't type this line : ` [self.window makeKeyAndVisible]; `. **2)** where does this line get *hiddenly* called when we simply use storyboard – Honey Sep 18 '16 at 22:23
  • @Travis. I did that but now the screen goes black for a few milliseconds before showing the view controller. Any ideas? – zulkarnain shah Nov 11 '17 at 03:07
  • Just in case anyone else does what I did- don't delete the "Launch screen interface file base name" from the "Info" tab, or else your viewcontrollers won't initialize to the correct size (https://stackoverflow.com/questions/42440623/appdelegate-window-initialisation-does-not-have-correct-size) Leaving that key alone is fine; you won't get any errors with it left in there. – NickGlowsinDark Oct 11 '19 at 01:28
  • 1
    In **Xcode 12**, you also have to remove the following value from the Info.plist file of the project : Application Scene Manifest > Scene Configuration > Application Session Role > Item 0 > delete **Storyboard Name - Main**. Otherwise you will have a crash during the app launch. – AnthonyR Oct 07 '20 at 21:28
125

For all the Swift lovers out there, here is the answer by @Travis translated into SWIFT:

Do what @Travis explained before the Objective C code. Then,

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

    self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
    let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    var exampleViewController: ExampleViewController = mainStoryboard.instantiateViewControllerWithIdentifier("ExampleController") as! ExampleViewController

    self.window?.rootViewController = exampleViewController

    self.window?.makeKeyAndVisible()

    return true
}

The ExampleViewController would be the new initial view controller you would like to show.

The steps explained:

  1. Create a new window with the size of the current window and set it as our main window
  2. Instantiate a storyboard that we can use to create our new initial view controller
  3. Instantiate our new initial view controller based on it's Storyboard ID
  4. Set our new window's root view controller as our the new controller we just initiated
  5. Make our new window visible

Enjoy and happy programming!

Victor Sigler
  • 22,039
  • 12
  • 83
  • 98
Display name
  • 1,701
  • 2
  • 11
  • 16
  • i was ask @Travis for this version , and then ... . thanks any way. – dellos Jul 04 '15 at 07:26
  • Storyboard ID is under the Identity section in the Identity inspector pane – Dominic Apr 19 '16 at 14:29
  • 2
    A tip to not need storyboard ID is to set explicitly the initial view controller (rootViewController) in the storyboard, and use the instance method UIStoryboard.instantiateInitialViewController() to get the controller instead of UIStoryboard.instantiateViewControllerWithIdentifier() proposed above. The rest is the same. – Eric Boumendil May 29 '16 at 16:49
47

You can programmatically set the key window's rootViewController in (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions

for example:

- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    if (shouldShowAnotherViewControllerAsRoot) {
        UIStoryboard *storyboard = self.window.rootViewController.storyboard;
        UIViewController *rootViewController = [storyboard instantiateViewControllerWithIdentifier:@"rootNavigationController"];
        self.window.rootViewController = rootViewController;
        [self.window makeKeyAndVisible];
    }

    return YES;
}
fontno
  • 6,004
  • 4
  • 33
  • 42
Chengjiong
  • 1,232
  • 11
  • 17
  • How to then initiate the original entrypoint from the secondary UIViewController? – ooxio Aug 03 '15 at 11:29
  • @ooxio: you can store the original entrypoint in a global place then use it later on. – Chengjiong Aug 04 '15 at 01:06
  • this is really useful if you want to instantiate to login/register or something like that... – Honey Sep 18 '16 at 22:13
  • This is so much more straightforward than @Travis's answer above because you don't have to go messing with a million project settings and tinkering in IB. Who cares if one of your view controllers is technically the default initial VC and then you programmatically divert to a different one? – Danny Oct 11 '16 at 19:15
  • Note that the replaced, storyboard-designated initial View Controller will still get instantiated and go through the `init()` / `deinit()` cycle, but without executing `viewDidLoad()` or properly initializing `IBOutlet`-s. Make sure you code is ready for it. – Gary Aug 21 '17 at 08:12
  • This is a great way to add support for iOS 11's `UIDocumentBrowserViewController` while conditionally maintaining support for iOS 10.x users via whatever existing mechanism was used. – JKaz Sep 07 '17 at 15:56
17

SWIFT 5

If you don't have a ViewController set as the initial ViewController in storyboard, you need to do 2 things:

  1. Go to your project TARGETS, select your project -> General -> Clear the Main Interface field.
  2. Always inside project TARGETS, now go to Info -> Application Scene Manifest -> Scene Configuration -> Application Session Role -> Item0 (Default Configuration) -> delete the storyboard name field.

Finally, you can now add your code in SceneDelegate:

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
    // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
    // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
    guard let windowScene = (scene as? UIWindowScene) else { return }

    window = UIWindow(windowScene: windowScene)


    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    // Make sure you set an Storyboard ID for the view controller you want to instantiate
    window?.rootViewController = storyboard.instantiateViewController(withIdentifier: identifier)
    window?.makeKeyAndVisible()

}
rs7
  • 1,423
  • 1
  • 5
  • 15
  • 2
    This is certainly the most current answer as of Xcode 11.5, and indeed fixed the `Failed to instantiate the default view controller for UIMainStoryboardFile 'Main' - perhaps the designated entry point is not set` warning I was having after I decided to instantiate my initial VC in code. An important point, when @rs7 says "delete the storyboard name field", they mean the whole row of the plist, not just the content of the field itself. – cdf1982 Jun 21 '20 at 08:32
15

Swift 3: Update to @victor-sigler's code

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

    // Assuming your storyboard is named "Main"
    let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)

    // Add code here (e.g. if/else) to determine which view controller class (chooseViewControllerA or chooseViewControllerB) and storyboard ID (chooseStoryboardA or chooseStoryboardB) to send the user to

    if(condition){
        let initialViewController: chooseViewControllerA = mainStoryboard.instantiateViewController(withIdentifier: "chooseStoryboardA") as! chooseViewControllerA
        self.window?.rootViewController = initialViewController
    )
    }else{
        let initialViewController: chooseViewControllerB = mainStoryboard.instantiateViewController(withIdentifier: "chooseStoryboardB") as! chooseViewControllerB
        self.window?.rootViewController = initialViewController
    )

    self.window?.makeKeyAndVisible(

    return true
}
MEK
  • 163
  • 1
  • 4
10

You can set Navigation rootviewcontroller as a main view controller. This idea can use for auto login as per application requirement.

UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"Main" bundle: nil];

UIViewController viewController = (HomeController*)[mainStoryboard instantiateViewControllerWithIdentifier: @"HomeController"];

UINavigationController navController = [[UINavigationController alloc] initWithRootViewController:viewController];

 self.window.rootViewController = navController;

if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {

    // do stuff for iOS 7 and newer

    navController.navigationBar.barTintColor = [UIColor colorWithRed:88/255.0 green:164/255.0 blue:73/255.0 alpha:1.0];

    navController.navigationItem.leftBarButtonItem.tintColor = [UIColor colorWithRed:88/255.0 green:164/255.0 blue:73/255.0 alpha:1.0];

    navController.navigationBar.tintColor = [UIColor whiteColor];

    navController.navigationItem.titleView.tintColor = [UIColor whiteColor];

    NSDictionary *titleAttributes =@{

                                     NSFontAttributeName :[UIFont fontWithName:@"Helvetica-Bold" size:14.0],

                                     NSForegroundColorAttributeName : [UIColor whiteColor]

                                     };

    navController.navigationBar.titleTextAttributes = titleAttributes;

    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];

}

else {

    // do stuff for older versions than iOS 7

    navController.navigationBar.tintColor = [UIColor colorWithRed:88/255.0 green:164/255.0 blue:73/255.0 alpha:1.0];



    navController.navigationItem.titleView.tintColor = [UIColor whiteColor];

}

[self.window makeKeyAndVisible];

For StoryboardSegue Users

UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"Main" bundle: nil];

// Go to Login Screen of story board with Identifier name : LoginViewController_Identifier

LoginViewController *loginViewController = (LoginViewController*)[mainStoryboard instantiateViewControllerWithIdentifier:@“LoginViewController_Identifier”];

navigationController = [[UINavigationController alloc] initWithRootViewController:testViewController];

self.window.rootViewController = navigationController;

[self.window makeKeyAndVisible];

// Go To Main screen if you are already Logged In Just check your saving credential here

if([SavedpreferenceForLogin] > 0){
    [loginViewController performSegueWithIdentifier:@"mainview_action" sender:nil];
}

Thanks

Bhavsar1311
  • 523
  • 4
  • 8
7

Open mainstoryboard, select the view that you want start first, then open Utilities--> Attributes. Below the "View Controller" you see the "Is initial View Controller" radio button. Just select it.

--- To the revised question:

May be you can try this: write a method in ViewDidLoad section of your inital view and when the method runs on application launch, method triggers a segue to another view.

m.etka
  • 405
  • 4
  • 10
  • I wrote the method in the ViewDidLoad but it didn't work and when I wright it in the viewdidAppear it is working, can you explain why this happening. – UserDev May 24 '12 at 12:49
  • May be you should try this: Add a segue code according to your conditions to one of the appropriate methods in the appDelegate.m file. For example, you can add a segue code to the "applicationDidBecomeActive:" method. – m.etka Jun 11 '12 at 15:05
  • @Jagdev you write it in ViewDidAppear instead of ViewDidLoad. – Umair Khan Jadoon Aug 28 '12 at 16:39
  • problem with this approach is the initial view controller appears becomes visible for some time and then switches to other which is not good from UX point of view so not a good solution. – vishal dharankar Feb 13 '14 at 12:57
3

I don't think it's possible. Instead you can have one initial controller which will have segues to different view controllers. On startup, you can decide which segue to perform programmatically.

Shmidt
  • 15,652
  • 16
  • 79
  • 129
3

You can set initial view controller using Interface Builder as well as programmatically.

Below is approach used for programmatically.

Objective-C :

        self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
        UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];

        UIViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:@"HomeViewController"]; // <storyboard id>

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

        return YES;

Swift :

        self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
        let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)

        var objMainViewController: MainViewController = mainStoryboard.instantiateViewControllerWithIdentifier("MainController") as! MainViewController

        self.window?.rootViewController = objMainViewController

        self.window?.makeKeyAndVisible()

        return true
Jayprakash Dubey
  • 32,447
  • 16
  • 161
  • 169
3

In AppDelegate.swift you can add the following code:

let sb = UIStoryboard(name: "Main", bundle: nil)
let vc = sb.instantiateViewController(withIdentifier: "YourViewController_StorboardID")
self.window?.rootViewController = vc
self.window?.makeKeyAndVisible()

Of course, you need to implement your logic, based on which criteria you'll choose an appropriate view controller.

Also, don't forget to add an identity (select storyboard -> Controller Scene -> Show the identity inspector -> assign StorboardID).

Hasan A Yousef
  • 15,770
  • 15
  • 88
  • 140
Nedim Talovic
  • 109
  • 1
  • 4
3

Another solution with using Swift 3 and Swift 4 with avoiding force casting is like this

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    self.window = UIWindow(frame: UIScreen.main.bounds)
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    guard let viewController = storyboard.instantiateViewController(withIdentifier: "YourViewController") as? YourViewController else {
        return false
    }
    self.window?.rootViewController = viewController
    self.window?.makeKeyAndVisible()
    return true
}

And below is using with UINavigationController

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    self.window = UIWindow(frame: UIScreen.main.bounds)
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    guard let viewController = storyboard.instantiateViewController(withIdentifier: "YourViewController") as? YourViewController else {
        return false
    }
    let navigationController = UINavigationController(rootViewController: viewController)
    self.window?.rootViewController = navigationController
    self.window?.makeKeyAndVisible()
    return true
}
abdullahselek
  • 6,297
  • 2
  • 39
  • 32
2

I created a routing class to handle dynamic navigation and keep clean AppDelegate class, I hope it will help other too.

//
//  Routing.swift
// 
//
//  Created by Varun Naharia on 02/02/17.
//  Copyright © 2017 TechNaharia. All rights reserved.
//

import Foundation
import UIKit
import CoreLocation

class Routing {

    class func decideInitialViewController(window:UIWindow){
        let userDefaults = UserDefaults.standard
        if((Routing.getUserDefault("isFirstRun")) == nil)
        {
            Routing.setAnimatedAsInitialViewContoller(window: window)
        }
        else if((userDefaults.object(forKey: "User")) != nil)
        {
            Routing.setHomeAsInitialViewContoller(window: window)
        }
        else
        {
            Routing.setLoginAsInitialViewContoller(window: window)
        }

    }

    class func setAnimatedAsInitialViewContoller(window:UIWindow) {
        Routing.setUserDefault("Yes", KeyToSave: "isFirstRun")
        let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
        let animatedViewController: AnimatedViewController = mainStoryboard.instantiateViewController(withIdentifier: "AnimatedViewController") as! AnimatedViewController

        window.rootViewController = animatedViewController
        window.makeKeyAndVisible()
    }

    class func setHomeAsInitialViewContoller(window:UIWindow) {
        let userDefaults = UserDefaults.standard
        let decoded  = userDefaults.object(forKey: "User") as! Data
        User.currentUser = NSKeyedUnarchiver.unarchiveObject(with: decoded) as! User

        if(User.currentUser.userId != nil && User.currentUser.userId != "")
        {
            let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
            let homeViewController: HomeViewController = mainStoryboard.instantiateViewController(withIdentifier: "HomeViewController") as! HomeViewController
            let loginViewController: UINavigationController = mainStoryboard.instantiateViewController(withIdentifier: "LoginNavigationViewController") as! UINavigationController
            loginViewController.viewControllers.append(homeViewController)
            window.rootViewController = loginViewController
        }
        window.makeKeyAndVisible()
    }

    class func setLoginAsInitialViewContoller(window:UIWindow) {
        let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
        let loginViewController: UINavigationController = mainStoryboard.instantiateViewController(withIdentifier: "LoginNavigationViewController") as! UINavigationController

        window.rootViewController = loginViewController
        window.makeKeyAndVisible()
    }

  class func setUserDefault(_ ObjectToSave : Any?  , KeyToSave : String)
    {
        let defaults = UserDefaults.standard

        if (ObjectToSave != nil)
        {

            defaults.set(ObjectToSave, forKey: KeyToSave)
        }

        UserDefaults.standard.synchronize()
    }

    class func getUserDefault(_ KeyToReturnValye : String) -> Any?
    {
        let defaults = UserDefaults.standard

        if let name = defaults.value(forKey: KeyToReturnValye)
        {
            return name as Any
        }
        return nil
    }

    class func removetUserDefault(_ KeyToRemove : String)
    {
        let defaults = UserDefaults.standard
        defaults.removeObject(forKey: KeyToRemove)
        UserDefaults.standard.synchronize()
    }

}

And in your AppDelegate call this

 self.window = UIWindow(frame: UIScreen.main.bounds)
 Routing.decideInitialViewController(window: self.window!)
Varun Naharia
  • 4,836
  • 7
  • 42
  • 73
2

UPDATED ANSWER for iOS 13 and scene delegate:

make sure in your info.plist file you go into Application Scene Manifest -> Scene Configuration -> Application Session Role -> Item 0 and delete the reference to the main storyboard there as well. Otherwise you'll get the same warning about failing to instantiate from storyboard.

Also, move the code from the app delegate to the scene delegate method scene(_:willConnectTo:options:), since this is where life cycle events are handled now.

bze12
  • 388
  • 2
  • 11
1

A few days ago I've encountered to same situation. A very simple trick solved this problem. I set hidden my initial view controller before launch2. If initial view controller is the right controller it's set to visible in viewDidLoad. Else, a segue is performed to desired view controller. It works perfectly in iOS 6.1 and above. I'm sure it works on earlier versions of iOS.

m.etka
  • 405
  • 4
  • 10
1

Thanks modified this as follows in AppDelegate:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) ->     Bool {
//Some code to check value of pins

if pins! == "Verified"{
        print(pins)
        self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
        let mainStoryboard: UIStoryboard = UIStoryboard(name: "HomePage", bundle: nil)
        let exampleViewController: UINavigationController = mainStoryboard.instantiateViewControllerWithIdentifier("SBHP") as! UINavigationController

        self.window?.rootViewController = exampleViewController

        self.window?.makeKeyAndVisible()
    }else{
        print(pins)
        self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
        let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
        let exampleViewController: UINavigationController = mainStoryboard.instantiateViewControllerWithIdentifier("SBUser") as! UINavigationController

        self.window?.rootViewController = exampleViewController

        self.window?.makeKeyAndVisible()
    }
Jeremy
  • 145
  • 1
  • 1
  • 12
1

Found simple solution - no need to remove "initial view controller check" from storyboard and editing project Info tab and use makeKeyAndVisible, just place

self.window.rootViewController = rootVC;

in

- (BOOL) application:didFinishLaunchingWithOptions:
alex1704
  • 339
  • 3
  • 4
1
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
let vc = mainStoryboard.instantiateViewController(withIdentifier: "storyBoardid") as! ViewController
let navigationController = UINavigationController(rootViewController: vc)
UIApplication.shared.delegate.window?.rootViewController = navigationController

Another way is to present viewController,

let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
let vc = mainStoryboard.instantiateViewController(withIdentifier: "storyBoardid") as! ViewController
self.present(vc,animated:true,completion:nil)

First you need to create object of your storyboard then change root(if required) then you take reference of particular view controller which is pushed current view controller(if you change root) else it's just present new view controller which may you

VDPurohit
  • 1,007
  • 1
  • 8
  • 21
1

Swift 4, Xcode 9

in file AppDelegate.swift

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let firstVC = storyboard.instantiateViewController(withIdentifier: "firstViewController") as! firstViewController
    self.window?.rootViewController = firstVC
}
Shan Ye
  • 2,372
  • 15
  • 21
1
 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        self.window = UIWindow(frame: UIScreen.main.bounds)
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        if (PreferenceHelper.getAccessToken() != "") {
            let initialViewController = storyboard.instantiateViewController(withIdentifier: "your View Controller Identifier")
            self.window?.rootViewController = initialViewController
        } else {
            let initialViewController = storyboard.instantiateViewController(withIdentifier: "your View Controller identifier")
            self.window?.rootViewController = initialViewController
        }
        self.window?.makeKeyAndVisible()
        return true
    }

/*
use your view Controller identifier must use it doubles quotes**strong text**
charles
  • 11
  • 2
  • checking on nsuser Defaults value preferences value Completly Stored and Checking Condition on in intial view Controller Problem – charles May 30 '18 at 09:19
1

Swift 5 or above# make route view controller by this simple code. If you are using xcode 11 or above first initialise var window: UIWindow? in AppDelegate

let rootVC = mainStoryboard.instantiateViewController(withIdentifier: "YOURCONTROLLER") as! YOURCONTROLLER

        navigationController.setNavigationBarHidden(true, animated: true)
        UIApplication.shared.windows.first?.rootViewController = UINavigationController.init(rootViewController: rootVC)
        UIApplication.shared.windows.first?.makeKeyAndVisible()
Rohit Nishad
  • 164
  • 1
  • 5
1

If you prefer not to change applicationDidFinish, you can do the following trick:

Set Navigation controller as an initial view controller and assign to it a custom class 'MyNavigationController'. Then you can tweak its root view controller during viewDidLoad - it will override the root view controller that you set in your storyboard.

class MyNavigationController: UINavigationController {
    override func viewDidLoad() {
        super.viewDidLoad()
        if !isLoggedIn() {
            viewControllers = [R.storyboard.authentication.loginView()!]
        }
    }

    private func isLoggedIn() -> Bool {
        return false
    }

}
Kamen Dobrev
  • 1,232
  • 13
  • 18
0

Xcode 12.4 Swift 5

in SceneDelegate.Swift

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    guard let windowScene = (scene as? UIWindowScene) else { return }
    let window = UIWindow(windowScene: windowScene)
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    window.rootViewController = storyboard.instantiateViewController(withIdentifier: "UserViewController") as! UserViewController
    
    self.window = window
    window.makeKeyAndVisible()
}

You can add your condition which view controller scene will dispaly

Neha
  • 618
  • 1
  • 9
  • 15
-3

Select the view controller which you want to open first and go to attribute inspector. Go to initial scene and check is initial view controller option.

Now this will be your initial view controller that will open first when application launch.

iMash
  • 1,138
  • 1
  • 12
  • 31