Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting Initial View Controller Programmatically Swift

I have seen lengthy Objective-C answers to this here on stack overflow, but no swift answers.

How can I change the initial view controller programmatically in swift, from a view controller?

I would think it would go something like this:

let storyboard = UIStoryboard(name: "Main", bundle: nil)
storyboard.setInitialViewController(identifier: ViewController())

But no, this doesn't do anything. The first line is good, but the second line's functions just don't exist.

like image 753
owlswipe Avatar asked Mar 19 '16 19:03

owlswipe


2 Answers

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.

like image 105
Ankit Goel Avatar answered Nov 11 '22 05:11

Ankit Goel


Updated for Swift 3

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

    window = UIWindow(frame: UIScreen.main.bounds)
    window?.makeKeyAndVisible()

    window?.rootViewController = UINavigationController(rootViewController: ViewController())

    return true
}
like image 24
iAj Avatar answered Nov 11 '22 05:11

iAj