Programmatically Set the Initial View Controller Using Storyboards

Programmatically set the initial view controller using Storyboards

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;
}

Programmatically set the initial view controller using Storyboards in Xcode 11.2

iOS 13 has moved the windows setup from AppDelegate to SceneDelegate to support the use of (possibly multiple) scenes rather than a single window. You now have to do the setup like this:

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

var window: UIWindow?
let storyboard = UIStoryboard(name: "Main", bundle: nil)

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = scene as? UIWindowScene else { return }
let vc = storyboard.instantiateViewController (withIdentifier: "Primary") as! ViewController
window = UIWindow(windowScene: windowScene)
window?.rootViewController = vc
window?.makeKeyAndVisible()
}

set initial viewcontroller in appdelegate - swift

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
}

Set rootViewController programmatically not working, picking initial view controller from storyboard only in Xcode 11

Got the answer by doing some more google, i mean stackoverflow.

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

var window: UIWindow?
let storyboard = UIStoryboard(name: "Main", bundle: nil)

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = scene as? UIWindowScene else { return }
let vc = storyboard.instantiateViewController (withIdentifier: "Primary") as! ViewController
window = UIWindow(windowScene: windowScene)
window?.rootViewController = vc
window?.makeKeyAndVisible()
}

SceneDelegate is used for this purpose since iOS 13 not AppDelegate. Here is the link SceneDelegate example

Setting Initial View Controller Programmatically Swift

To do it in the view controller and not in the app delegate: Just fetch the reference to the AppDelegate in your view controller and reset it's window object with the right view controller as it's rootviewController.

Step 1: Make some NSUserDefaults the user can adjust. A couple of buttons, some switches in a table view, something. Then when the user taps the button, we change the NSUserDefault.

@IBAction func SwitchLaunchViewtoViewController2(sender: AnyObject) {
defaults.setObject("ViewController2", forKey: "LaunchView")
}
@IBAction func SwitchLaunchViewtoViewController1(sender: AnyObject) {
defaults.setObject("ViewController1", forKey: "LaunchView")
}

Hook a couple of buttons in a settings view controller up to these functions, and we've started.

Step 2: Set up Storyboard IDs for all the storyboards you want to be able to be set as the launch view. So, for each View Controller that could be an initial view controller:

-Head into your storyboard.

-Click on the view controller.

-In the sidebar at right, click on the newspaper-like icon, which you control the class in.

-In the "Identity" section (third row), check "Use Storyboard ID" (make sure it's on) and then type in something like "VC1" in the "Storyboard ID" text field. Make sure you choose a different Storyboard ID for each view controller.

-Repeat for each view controller.

Step 3: Set up your initial view controller in the AppDelegate.swift file. Head into the func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool section of your app delegate.

Add this to read from the NSUserDefault you created earlier:

let defaults = NSUserDefaults.standardUserDefaults()
if let launchview = defaults.stringForKey("LaunchView")
{

}

This looks for an NSUserDefault string called "LaunchView" (which you created in step 1) and sets it to the new variable launchview if it finds a matching NSUserDefault.

Then, inside the if let launchview... brackets, we want to check what you set your LaunchView to. For every object you set to LaunchView in step 1 (in the example, I did "ViewController2" and "ViewController1"), you have to check for it here. So, inside those brackets, we add this:

if launchview == "ViewController2" {

} else if launchview == "ViewController1" {

}

Then, inside each of those if statements, we add the following code:

let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.window = UIWindow(frame: UIScreen.mainScreen().bounds)
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil) // this assumes your storyboard is titled "Main.storyboard"
let yourVC = mainStoryboard.instantiateViewControllerWithIdentifier("YOUR_VC_IDENTIFIER") as! YourViewController // inside "YOUR_VC_IDENTIFIER" substitute the Storyboard ID you created in step 2 for the view controller you want to open here. And substitute YourViewController with the name of your view controller, like, for example, ViewController2.
appDelegate.window?.rootViewController = yourVC
appDelegate.window?.makeKeyAndVisible()

This will open the chosen window when your application finishes loading after it's been in the background a while.

Your finished didFinishLoadingWithOptions section of your AppDelegate might look something like this:
(don't just copy and paste, read the instructions above)

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

let defaults = NSUserDefaults.standardUserDefaults()
if let launchview = defaults.stringForKey("LaunchView")
{

if launchview == "ViewController1" {

let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.window = UIWindow(frame: UIScreen.mainScreen().bounds)
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let yourVC = mainStoryboard.instantiateViewControllerWithIdentifier("VC1") as! ViewController1
appDelegate.window?.rootViewController = yourVC
appDelegate.window?.makeKeyAndVisible()

} else if launchview == "ViewController2" {
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.window = UIWindow(frame: UIScreen.mainScreen().bounds)
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let yourVC = mainStoryboard.instantiateViewControllerWithIdentifier("VC1") as! ViewController1
appDelegate.window?.rootViewController = yourVC
appDelegate.window?.makeKeyAndVisible()
}

}

return true
}

I hope this helps you, and many thanks to Ankit Goel who helped me with this one so much. Read the comments down below for more.

One final note: if you are using switches in a settings view, make sure on the viewDidLoad of that settings view controller you read from the NSUserDefault LaunchView which one the user selected last.

How to change the initial view controller through swift code

Implement this logic in your appdelegate class:

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

let isRegistered = NSUserDefaults.standardUserDefaults().boolForKey("ALLREADY_REGISTER")

if isRegistered == true{
// implement home view controller
let homeViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("HomeVC") as! HomeViewController
self.window?.rootViewController = homeViewController
self.window?.makeKeyAndVisible()

}else{
// implement register view controller
let registerViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("RegisterVC") as! RegisterViewController
self.window?.rootViewController = registerViewController
self.window?.makeKeyAndVisible()
}

return true
}

Then when first time register completed successfully then set bool variable true for the key ALLREADY_REGISTER

NSUserDefaults.standardUserDefaults().setBool(true, forKey: "ALLREADY_REGISTER")`

Storyboard's view controller not showing up when programmatically set as root view controller

You need to initialize the window programmatically.

Try adding the following to the beginning of your didFinishLaunchingWithOptions method in Appdelegate

self.window = UIWindow()

Also in your showPermissionVC and showContainerVC methods, replace this line:

UIApplication.shared.windows.first?.rootViewController = rootVC

with:

window?.rootViewController = rootVC

How to set initial storyboard

You do not set an initial storyboard programmatically.

Here's how it works. Either you have a main storyboard listed in Xcode under Main Interface or you don't:

  • If you do, that is the initial storyboard, period. That storyboard is loaded automatically at launch time, and its initial view controller becomes the window's root view controller (and the interface is then displayed automatically).

  • If you don't (that is, if the Main Interface field is empty), then nothing happens automatically. It is up to your code to obtain a view controller, somehow (possibly from a storyboard), and make its the window's root view controller (and to show the interface).

So, to sum up, either everything happens automatically or nothing happens automatically. There is no intermediate state, as you seem to imagine, in which you can programmatically change things so that a different storyboard is loaded automatically.

There is, however, a kind of intermediate state where you permit the Main Interface storyboard to load but then you ignore it. In your implementation of application:didFinishLoading..., you would then sometimes do the thing I said in the second bullet point, i.e. load a different view controller and make it the root view controller. This works because the automatic stuff I mentioned in the first bullet point has already happened by the time application:didFinishLoading... is called. So, in effect, your code sometimes permits that automatic stuff and sometimes overrides it.

In this example from my own code, we either use the Main Interface storyboard to load the initial view controller or we load a different view controller from the storyboard ourselves, depending on a value in User Defaults:

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

if let rvc = self.window?.rootViewController {
if NSUserDefaults.standardUserDefaults().objectForKey("username") as? String != nil {
self.window!.rootViewController = rvc.storyboard!.instantiateViewControllerWithIdentifier("root")
}
}
return true
}

How to set initial view controller for swiftUI

In SceneDelegate.swift

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
let contentView = ContentView().environment(\.managedObjectContext, context)

if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
window.makeKeyAndVisible()
}
}

change the line let contentView = ContentView()... to YourInitialView()...

The result should look like this

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// change this line to your initial view controller class name
let contentView = YourInitalView().environment(\.managedObjectContext, context)
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
window.makeKeyAndVisible()
}
}


Related Topics



Leave a reply



Submit