以编程方式更改storyBoard的rootViewController

63

我使用Storyboards创建了我的项目。根ViewController位于一个Storyboard中,我在appDelegate中没有编写任何代码。

现在我想展示一下我的应用程序,所以我想将根ViewControllerTab Bar更改为我的TourVC,当应用程序的导览完成后,我想再次将根ViewController切换回Tab Bar

因此,我在网上查找并按照以下步骤进行操作:

1)从app.plist文件中删除Storyboards, 2)取消选中Storyboards中“isInitialViewController”选项,在Tab Bar控制器的情况下检查它,因为它是一个根ViewController, 3)将此代码添加到appDelegate.m文件中。

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;

但是我的应用程序在运行时崩溃,出现以下错误日志:

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

同时我也收到了一个警告,

Unsupported Configuration: Scene is unreachable due to lack of entry points and does not have an identifier for runtime access via -instantiateViewControllerWithIdentifier:.
9个回答

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()

或者简单来说就是这样:

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

两者都工作正常!


那么,从 plist 文件中删除 storyBoard,并取消勾选 intialViewController 怎么样?另外,newRootVC 不在 storyBoard 中。 - Ranjit
1
你的根视图控制器将被更改,因此不会有故事板。 - Sunny Shah
不,它不起作用,因为我的tabBarController已经在故事板中了。那么为什么要再创建一次呢? - Ranjit
1
我已经编辑了代码并提交了修改。我正在我的应用程序中使用它。 - LpLrich
3
只是想提醒,在 didFinishLaunchingWithOptions 方法中应用程序尚未设置 keyWindow,因此在这种情况下应该使用 self.window.rootViewController = ... - Anton Gaenko
显示剩余8条评论

11

在你的主故事板中为你的类设置故事板ID。

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;

请检查上面的内容。 - Ranjit
你好 @Mayank,你收到了吗? - Ranjit
抱歉,ApplicationBecomeActive 中有一些代码导致了这个问题,现在已经解决了。谢谢大家,你们是对的。 - Ranjit
你好,现在在应用程序启动时,我将我的ProductTour VC设置为rootVC,现在当用户退出ProductTour时,我想再次将我的root VC转移到TabBar,该怎么做? - Ranjit

7
在 Swift 中,我们可以按以下方式实现它:
let storyboard = UIStoryboard(name: "StartingPage", bundle: NSBundle.mainBundle())      
let loginView: SignInVC = storyboard.instantiateViewControllerWithIdentifier("SignInVC") as! SignInVC
UIApplication.sharedApplication().keyWindow?.rootViewController = loginView

4

Swift 5 + Xcode 11:

这样做:

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

或者像这样:

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

两者都可以正常工作!


我在我的场景代理(willConnectTo)中使用了第一个答案,它是有效的,但当我强制关闭应用程序并再次打开时,应用程序无法打开。如果在应用程序代理中更改根视图控制器,则其效果不佳。 - Rana Ali Waseem

3

补充Sunny Shah的回答,这是它的Swift 3版本:

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

3
我使用简单的方法:
UIStoryboard *sb = [UIStoryboard storyboardWithName:@"NameOfStoryBoard" bundle:nil];
UITabBarController *rootViewController = [sb instantiateViewControllerWithIdentifier:@"NameOfTabBarController"];
[[UIApplication sharedApplication].keyWindow setRootViewController:rootViewController];

14
这段代码片段与被接受的答案有何不同? - Dmitry Grigoryev

3

Swift 3 代码:

在 didFinishLaunchingWithOptions Appdelegate 函数中使用以下代码。 将 "HomeViewController" 替换为你想要设置为应用程序启动时的根视图控制器的 ViewController。

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

谢谢你的想法。这对我有用:<code>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 } </code> - rudifa

2

Objective C

步骤1:从info.plist中删除主storyboard。

步骤2:在你的接口构建器中为你的视图控制器添加storyboard ID。

步骤3:在应用程序委托的application did finish方法中添加以下代码。

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

2

这是一篇旧文章,但我会回复。

我不推荐以下代码。

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

因为您正在创建两个实例。 我建议在适当的ViewController中编写以下代码。

let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window?.rootViewController = self

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接