62

I have created my project using Storyboards. The root ViewController lies inside a Storyboard, I have not written a single code in the appDelegate.

Now I want to show a tour of my app, so I want to change the root ViewController from Tab Bar to my TourVC and when the tour of the app is finished , I want to again switch back my root ViewController to Tab Bar.

So I looked up online and followed the following points

1) Remove Storyboards from app.plist file, 2) Uncheck option "isInitialViewController" from Storyboards which is checked in case of Tab Bar controller because its a root ViewController, 3) Add this code in appDelegate.m file.

self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
ProductTourViewController *PT = [[ProductTourViewController alloc] initWithNibName:@"ProductTourViewController" bundle:nil];
self.window.rootViewController = PT;
[self.window makeKeyAndVisible];
return YES;

But my app crashes with this error log,

[ProductTourViewController selectedViewController]: unrecognized selector sent to instance 0x1766a9e0

And also I get a warning,

Unsupported Configuration: Scene is unreachable due to lack of entry points and does not have an identifier for runtime access via -instantiateViewControllerWithIdentifier:.
Cœur
  • 37,241
  • 25
  • 195
  • 267
Ranjit
  • 4,576
  • 11
  • 62
  • 121

9 Answers9

175

Objective-C:

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
UITabBarController *rootViewController = [storyboard instantiateViewControllerWithIdentifier:@"tabBarcontroller"];
[[UIApplication sharedApplication].keyWindow setRootViewController:rootViewController];

Swift :

 let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
 let viewController = mainStoryboard.instantiateViewControllerWithIdentifier("tabBarcontroller") as UITabBarController  
   UIApplication.sharedApplication().keyWindow?.rootViewController = viewController;

Swift 3:

let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let viewController = mainStoryboard.instantiateViewController(withIdentifier: "tabBarcontroller") as! UITabBarController
UIApplication.shared.keyWindow?.rootViewController = viewController

Swift 5:

let viewController = mainStoryboard.instantiateViewController(withIdentifier: "tabBarcontroller") as! UITabBarController
UIApplication.shared.windows.first?.rootViewController = viewController
UIApplication.shared.windows.first?.makeKeyAndVisible()

Or simply like this:

let viewController = mainStoryboard.instantiateViewController(withIdentifier: "tabBarcontroller") as! UITabBarController
self.view.window?.rootViewController = viewController
self.view.window?.makeKeyAndVisible()

Both works fine!

Carlos Irano
  • 682
  • 7
  • 8
Sunny Shah
  • 12,990
  • 9
  • 50
  • 86
  • So what about removing storyBoard from plist file and unchecking intialViewController. Also the newRootVC is not inside storyBoard. – Ranjit Mar 26 '14 at 07:26
  • 1
    no storyboard will be there your root viewcontroller will be changed – Sunny Shah Mar 26 '14 at 07:29
  • Hello, now on application launch, I made my productTour VC as the rootVC, now when the user exits ProductTour, I want to again shift my root VC to TabBar, how to do that – Ranjit Mar 26 '14 at 11:26
  • use the same code replace with [[UIApplication sharedApplication].keyWindow setRootViewController:TabBarObj]; – Sunny Shah Mar 26 '14 at 11:27
  • no its not working, because my tabBarController is in storyboard already. So why to create it once again – Ranjit Mar 26 '14 at 11:32
  • if it is in storyboard then get from the storyboard and set rootviewcontroller. see my updated answer – Sunny Shah Mar 26 '14 at 16:55
  • Ok , i will try it and get back to you – Ranjit Mar 26 '14 at 16:57
  • 1
    I have edited the code and submitted the edits. I am using it in my application. – LpLrich Aug 19 '14 at 20:14
  • 3
    just want to note that during `didFinishLaunchingWithOptions` application haven't set keyWindow yet, so you should using `self.window.rootViewController = ...` in such case – Anton Gaenko Oct 14 '14 at 12:19
  • Just wanted to say THANK YOU! Sid you solved a problem I was having for months! :) – Joshua Hart Jan 31 '15 at 20:05
  • Last line did not worked for me. So, use [self.window setRootViewController:WelcomeVC]; – Jabbar Sep 10 '15 at 09:11
  • Totally unrelated to what I was doing, but your code helped me solve my own problem! Thanks man. Upvote from me! ;) – Christopher Smit Jun 14 '17 at 19:24
  • This right here was the real killer for me: `UIApplication.shared.keyWindow?.rootViewController`. This `self.window?.rootViewController` never worked. Thanks! – Kilmazing Nov 19 '19 at 03:33
11

enter image description here Set storyboard ID for your class in your main storyboard.

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

UINavigationController *controller = (UINavigationController*)[MainStoryboard
                                                                           instantiateViewControllerWithIdentifier: @"RootNavigationController"];


LoginViewController *login=[MainStoryboard instantiateViewControllerWithIdentifier:@"LoginViewController"];
            [controller setViewControllers:[NSArray arrayWithObject:login] animated:YES];
self.window.rootViewController=controller;
Mayank Jain
  • 5,663
  • 7
  • 32
  • 65
  • same as above in my question ...please check – Ranjit Mar 26 '14 at 09:37
  • Hello @Mayank, did you get it. – Ranjit Mar 26 '14 at 09:44
  • Guys sorry, there was some code in ApplicationBecomeActive, which was causing this problem and its solved now. thanks everyone, you are right. – Ranjit Mar 26 '14 at 10:16
  • Hello, now on application launch, I made my productTour VC as the rootVC, now when the user exits ProductTour, I want to again shift my root VC to TabBar, how to do that – Ranjit Mar 26 '14 at 11:26
7

In swift we can implement it is as following

let storyboard = UIStoryboard(name: "StartingPage", bundle: NSBundle.mainBundle())      
let loginView: SignInVC = storyboard.instantiateViewControllerWithIdentifier("SignInVC") as! SignInVC
UIApplication.sharedApplication().keyWindow?.rootViewController = loginView
Nischal Hada
  • 3,230
  • 3
  • 27
  • 57
3

I use simple this:

UIStoryboard *sb = [UIStoryboard storyboardWithName:@"NameOfStoryBoard" bundle:nil];
UITabBarController *rootViewController = [sb instantiateViewControllerWithIdentifier:@"NameOfTabBarController"];
[[UIApplication sharedApplication].keyWindow setRootViewController:rootViewController];
MUHAMMAD WASIM
  • 191
  • 2
  • 11
3

Just to add to Sunny Shah's answer, this is the Swift 3 version of it:

        let mainStoryBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
        let viewController: UIViewController = mainStoryBoard.instantiateViewController(withIdentifier: "MainTabBarController") as! UITabBarController
        UIApplication.shared.keyWindow?.rootViewController = viewController
Aldo Gomez
  • 31
  • 1
  • 3
3

Swift 3 code:

Use below in didFinishLaunchingWithOptions Appdelegate function. Replace "HomeViewController" with ViewController you want to set as Root ViewController on app launch.

self.window = UIWindow(frame: UIScreen.main.bounds)

let storyboard = UIStoryboard(name: "Main", bundle: nil)

let initialViewController = storyboard.instantiateViewController(withIdentifier: "HomeViewController")

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

return true
Karan Dua
  • 2,401
  • 3
  • 15
  • 17
  • Thank you for the idea. This worked for me : func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { if ProcessInfo.processInfo.arguments.contains("XCUITests") { window?.layer.speed = 100.0 // speeds up the test in simulator about 3x } return true } – rudifa Jul 22 '18 at 16:48
3

Swift 5 + Xcode 11:

Make like this:

let viewController = mainStoryboard.instantiateViewController(withIdentifier: "tabBarcontroller") as! UITabBarController
UIApplication.shared.windows.first?.rootViewController = viewController
UIApplication.shared.windows.first?.makeKeyAndVisible()

Or like this:

let viewController = mainStoryboard.instantiateViewController(withIdentifier: "tabBarcontroller") as! UITabBarController
self.view.window?.rootViewController = viewController
self.view.window?.makeKeyAndVisible()

Both works fine!

Carlos Irano
  • 682
  • 7
  • 8
  • I'm using the first answer in my scene delegate (willConnectTo) it's working but when I kill the app forcefully and open it again then app is not opening. And if change root view controller in app delegate its not working fine. – Rana Ali Waseem Jan 05 '22 at 01:45
2

Objective c

step 1: remove main story board from info.plist

step 2: add storyboard id to your view controller in your interface builder

step 3: add the following code to application did finish method in app delegate

self.window = [[UIWindow alloc] initWithFrame: [UIScreen mainScreen].bounds];


//set main story board
if( condition){
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"StoryboardName1" bundle:nil];
    UIViewController *rootViewController = [storyboard instantiateViewControllerWithIdentifier:@"ViewController1"];
    [[UIApplication sharedApplication].keyWindow setRootViewController:rootViewController];
    [self window].rootViewController = rootViewController;
    [self.window makeKeyAndVisible];
}else{
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"StoryboardName2" bundle:nil];
    UIViewController *rootViewController = [storyboard instantiateViewControllerWithIdentifier:@"ViewController2"];
    [[UIApplication sharedApplication].keyWindow setRootViewController:rootViewController];
    [self window].rootViewController = rootViewController;
    [self.window makeKeyAndVisible];
}
Daniel Raouf
  • 2,307
  • 1
  • 22
  • 28
2

This is an old article, but I will reply. I do not recommend the following code.

let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let viewController = mainStoryboard.instantiateViewController(withIdentifier: "tabBarcontroller") as! UITabBarController
UIApplication.shared.keyWindow?.rootViewController = viewController

Because you are creating two instances. I recommend writing the following code in the appropriate ViewController.

let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window?.rootViewController = self
WaFuNuke
  • 37
  • 1
  • 10