使用 Storyboard 以编程方式设置初始视图控制器

Programmatically set the initial view controller using Storyboards

提问人:Jagdev Sendhav 提问时间:5/3/2012 最后编辑:CœurJagdev Sendhav 更新时间:3/27/2023 访问量:168527

问:

如何以编程方式设置 Storyboard?我想根据某些条件打开我的故事板以显示不同的视图,这些条件可能因启动而异。InitialViewController

iOS Objective-C Swift UIVieviceController UISstoryboard

评论

1赞 Borzh 3/22/2016
在不发出警告的情况下检查此答案,而不清除设置中的“主要情节提要”。

答:

-3赞 iMash 5/3/2012 #1

选择要首先打开的视图控制器,然后转到属性检查器。 转到初始场景并选中初始视图控制器选项。

现在,这将是您的初始视图控制器,它将在应用程序启动时首先打开。

7赞 m.etka 5/3/2012 #2

打开主情节提要,选择要首先启动的视图,然后打开“实用工具”-“>属性”。在“视图控制器”下方,您会看到“是初始视图控制器”单选按钮。只需选择它。

--- 对经修订的问题:

也许你可以试试这个:在初始视图的 ViewDidLoad 部分中编写一个方法,当该方法在应用程序启动时运行时,该方法会触发到另一个视图的 segue。

评论

0赞 Jagdev Sendhav 5/24/2012
我在 ViewDidLoad 中编写了该方法,但它不起作用,当我在 viewdidAppear 中打开它时,它正在工作,您能解释一下为什么会发生这种情况吗?
0赞 m.etka 6/11/2012
也许你应该试试这个:根据你的条件,将一个 segue 代码添加到 appDelegate.m 文件中的适当方法之一。例如,可以将 segue 代码添加到“applicationDidBecomeActive:”方法。
0赞 Umair Khan Jadoon 8/29/2012
@Jagdev在 ViewDidAppear 而不是 ViewDidLoad 中编写它。
0赞 vishal dharankar 2/13/2014
这种方法的问题是,初始视图控制器出现一段时间后变得可见,然后切换到其他视图控制器,从用户体验的角度来看,这并不好,所以不是一个好的解决方案。
3赞 Shmidt 5/3/2012 #3

我认为这是不可能的。 相反,你可以有一个初始控制器,它将具有与不同视图控制器的顺序。在启动时,您可以决定以编程方式执行哪个 segue。

481赞 Travis 2/18/2013 #4

如何在没有虚拟初始视图控制器的情况下使用

确保所有初始视图控制器都具有 Storyboard ID。

在情节提要中,取消选中第一个视图控制器中的“是初始视图控制器”属性。

如果此时运行应用,你将阅读

无法实例化 UIMainStoryboardFile 'MainStoryboard' 的默认视图控制器 - 可能未设置指定的入口点?

你会注意到,应用委托中的 window 属性现在是 nil。

在应用程序的设置中,转到您的目标和选项卡。其中明确了 的值。在选项卡上,清除 的值。这将删除警告。InfoMain storyboard file base nameGeneralMain Interface

在应用委托的方法中创建窗口和所需的初始视图控制器:application:didFinishLaunchingWithOptions:

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

评论

7赞 Hunkpapa 8/29/2013
爱!爱!爱!我将使用它在IOS6和IOS7的两个完全不同的视图控制器树之间切换。似乎是处理向后兼容性的最佳方法,同时仍然使用 IOS7 中的所有花里胡哨。
6赞 Raghavendra 8/11/2014
我正在学习 Swift 的 iOS 编程。谁能帮我如何在 swift 中编写上述代码。请帮忙。谢谢。
1赞 Travis 9/30/2014
在新进程中启动应用时,将调用 @bdv。如果转到主屏幕并返回到应用程序,则不会再次调用此方法。(除非 iOS 因内存限制而终止。尝试停止应用程序,然后从 IDE 再次启动。如果问题仍然存在,请将问题发布到 SO,我很乐意提供帮助,朋友。didFinishLaunchingWithOptions
2赞 Travis 1/8/2015
@peyman 根据我的调查,一旦删除了对主情节提要的引用,该窗口就不存在了。我在当前项目中注释了窗口实例化,发现情况仍然如此。
2赞 mjmayank 7/10/2015
@Raghav,这是 swift 代码:self.window = UIWindow(frame: UIScreen.mainScreen().bounds) var storyboard = UIStoryboard(name: "Main", bundle: nil) var viewController: UIViewController = // self.window!.rootViewController = viewController self.window!.makeKeyAndVisible()
47赞 Chengjiong 10/1/2013 #5

您可以通过编程方式将键窗口的 rootViewController 设置为(BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions

例如:

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

评论

0赞 ooxio 8/3/2015
然后如何从辅助 UIViewController 启动原始入口点?
0赞 Chengjiong 8/4/2015
@ooxio:您可以将原始入口点存储在全局位置,然后稍后使用。
0赞 mfaani 9/19/2016
如果您想实例化登录/注册或类似的东西,这非常有用......
0赞 Danny 10/12/2016
这比上面@Travis的答案要简单得多,因为你不必去搞乱一百万个项目设置和修补IB。谁在乎你的一个视图控制器在技术上是否是默认的初始 VC,然后你以编程方式转移到另一个?
0赞 Gary 8/21/2017
请注意,被替换的、情节提要指定的初始视图控制器仍将实例化并经历 / 循环,但不会执行或正确初始化 -s。确保您的代码已准备就绪。init()deinit()viewDidLoad()IBOutlet
1赞 m.etka 1/4/2014 #6

几天前,我遇到了同样的情况。一个非常简单的技巧解决了这个问题。 我在 launch2 之前设置了隐藏我的初始视图控制器。如果初始视图控制器是正确的控制器,则在 viewDidLoad 中将其设置为可见。否则,将对所需的视图控制器执行 segue。它在 iOS 6.1 及更高版本中完美运行。我敢肯定它适用于早期版本的 iOS。

128赞 Display name 12/7/2014 #7

对于所有 Swift 爱好者,以下是翻译成 SWIFT@Travis答案:

执行@Travis在 Objective C 代码之前解释的内容。然后

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
}

这将是您要显示的新初始视图控制器。ExampleViewController

步骤说明:

  1. 创建一个具有当前窗口大小的新窗口,并将其设置为我们的主窗口
  2. 实例化一个故事板,我们可以用它来创建新的初始视图控制器
  3. 根据其 Storyboard ID 实例化新的初始视图控制器
  4. 将新窗口的根视图控制器设置为我们刚刚启动的新控制器
  5. 使我们的新窗口可见

享受和快乐的编程!

评论

0赞 dellos 7/4/2015
我被问@Travis这个版本,然后......。无论如何,谢谢。
0赞 Dominic 4/19/2016
情节提要 ID 位于“标识检查器”窗格中的“标识”部分下
2赞 Eric Boumendil 5/30/2016
不需要情节提要 ID 的提示是在情节提要中显式设置初始视图控制器 (rootViewController),并使用实例方法 UIStoryboard.instantiateInitialViewController() 获取控制器,而不是上面建议的 UIStoryboard.instantiateViewControllerWithIdentifier()。其余的都是一样的。
10赞 Bhavsar1311 10/7/2015 #8

您可以将导航 rootviewcontroller 设置为主视图控制器。 这个想法可以根据应用程序要求用于自动登录。

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

对于 StoryboardSegue 用户

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

谢谢

3赞 Jayprakash Dubey 5/13/2016 #9

您可以使用Interface Builder进行设置,也可以通过编程方式进行设置。initial view controller

下面是以编程方式使用的方法。

目标-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;

迅速:

        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
1赞 Jeremy 5/15/2016 #10

谢谢在 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()
    }
1赞 alex1704 10/1/2016 #11

找到简单的解决方案 - 无需从故事板和编辑项目信息选项卡中删除“初始视图控制器检查”并使用,只需放置makeKeyAndVisible

self.window.rootViewController = rootVC;

- (BOOL) application:didFinishLaunchingWithOptions:

评论

0赞 thomers 10/11/2016
但你仍然从中得到,对吗?rootVCinstantiateViewControllerWithIdentifier
15赞 MEK 1/16/2017 #12

斯威夫特 3:更新@victor-sigler的代码

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
}

评论

0赞 Native_Mobile_Arch_Dev 2/21/2019
谢谢你,@MEK。此外,您可能希望通过将尾随括号替换为大括号来更正条件结束语句的语法。
3赞 Nedim Talovic 5/17/2017 #13

您可以在其中添加以下代码:AppDelegate.swift

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

当然,您需要实现您的逻辑,根据哪些条件选择合适的视图控制器。

此外,不要忘记添加标识(选择“情节提要”->“控制器场景”-“>”显示标识检查器“>分配 StorboardID)。

2赞 Varun Naharia 6/14/2017 #14

我创建了一个路由类来处理动态导航并保持干净的 AppDelegate 类,我希望它也能帮助其他人。

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

}

在 AppDelegate 中调用

 self.window = UIWindow(frame: UIScreen.main.bounds)
 Routing.decideInitialViewController(window: self.window!)
3赞 abdullahselek 8/4/2017 #15

使用 Swift 3Swift 4 避免强制转换的另一种解决方案是这样的

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
}

下面是与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
}
1赞 V D Purohit 12/7/2017 #16
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

另一种方式是呈现 viewController,

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

首先,您需要创建故事板的对象,然后更改root(如果需要),然后引用特定的视图控制器,该控制器被推送为当前视图控制器(如果您更改root),否则它只是存在新的视图控制器,这可能是

评论

0赞 Prags 12/7/2017
@V D Purohit,您能否详细描述一下您的答案,以便更好地理解。
1赞 Shan Ye 2/10/2018 #17

Swift 4、Xcode 9

文件 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
}
1赞 charles 5/30/2018 #18
 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**

评论

0赞 charles 5/30/2018
检查 nsuser 默认值 首选项值 完整存储并检查 初始视图中的条件开启 控制器问题
1赞 Rohit Nishad 2/26/2020 #19

Swift 5 或更高版本#通过这个简单的代码制作路由视图控制器。 如果您使用的是 xcode 11 或更高版本,请先在 AppDelegate 中初始化var window: UIWindow?

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()
21赞 rs7 4/28/2020 #20

斯威夫特 5

如果没有在情节提要中将 ViewController 设置为初始 ViewController,则需要执行 2 项操作:

  1. 转到您的项目 TARGETS,选择您的项目 -> 常规 -> 清除 Main Interface 字段。
  2. 始终在项目 TARGETS 中,现在转到“信息”-“>”应用程序场景清单“-”>场景配置“-”>应用程序会话角色“->”Item0(默认配置)“>删除”情节提要名称“字段。

最后,现在可以在 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()

}

评论

4赞 cdf1982 6/21/2020
这当然是截至 Xcode 11.5 的最新答案,并且确实修复了我决定在代码中实例化初始 VC 后遇到的警告。重要的一点是,当@rs7说“删除情节提要名称字段”时,它们指的是 plist 的整行,而不仅仅是字段本身的内容。Failed to instantiate the default view controller for UIMainStoryboardFile 'Main' - perhaps the designated entry point is not set
0赞 pkamb 9/2/2021
请注意,这是一个不同的 UIWindow 初始值设定项,而不是你可能在较旧的基于应用委托的代码中使用的初始值设定项。如果您要移植到新的做事方式,请务必更新它。使用旧的 Window 初始值设定项会导致黑屏UIWindow(windowScene: windowScene)initWithFrame:
3赞 bze12 5/8/2020 #21

如果您在 iOS 13+ 中使用场景委托:

确保在文件中找到以下行:Info.plist

Application Scene Manifest > Scene Configuration > Application Session Role > Item 0

并在此处删除对主情节提要的引用。否则,你将收到相同的警告,提示无法从 Storyboard 实例化。

此外,将代码从 app delegate 移动到 scene delegate 方法 ,因为这是现在处理生命周期事件的地方。scene(_:willConnectTo:options:)

1赞 Kamen Dobrev 6/9/2020 #22

如果您不想更改 applicationDidFinish,您可以执行以下技巧:

将导航控制器设置为初始视图控制器,并为其分配一个自定义类“MyNavigationController”。然后,您可以在 viewDidLoad 期间调整其根视图控制器 - 它将覆盖您在情节提要中设置的根视图控制器。

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

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

}
0赞 Neha 3/2/2021 #23

Xcode 12.4 斯威夫特 5

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

您可以添加视图控制器场景将显示的条件

0赞 yoAlex5 6/22/2021 #24

使用 Storyboards(而不是 Main)设置初始 ViewController

[Swift 5 和 Xcode 11]

  1. Main.storyboard->视图控制器 ->属性检查器 ->取消选中Is Initial View Controller

  2. 应用目标 -> 常规 ->全部删除Main Interface

  3. 编辑应用委托

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    
    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        self.window = UIWindow(frame: UIScreen.main.bounds)
        
        let storyboard: UIStoryboard = UIStoryboard(name: "SomeStoryboard", bundle: nil) //SomeStoryboard  is name of .storyboard
        let viewController: ViewController = storyboard.instantiateViewController(withIdentifier: "someStoryboardId") as! ViewController //someStoryboardId is Storyboard ID

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

        return true
    }
}
0赞 Hitesh 3/27/2023 #25

以下代码是目标 c。

以下代码将创建不带情节提要的自定义入口文件。

我在堆栈溢出上读到的所有答案都有以下代码,但它们缺少重要的行

MainViewController 是我想成为第一个要加载的视图控制器的 viewController。

- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
    UIWindowScene *winScreen = (UIWindowScene *)scene;
    self.window = [[UIWindow alloc] initWithWindowScene:winScreen];
    
    // Create a root view controller and set it as the root view controller of the navigation controller
    MainViewController *rootViewController = [[MainViewController alloc] init];
    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
    
    // Set the navigation controller as the root view controller of the window
    [self.window setRootViewController:navigationController];
    [self.window makeKeyAndVisible];
}

在这里我不知道为什么,但每个答案都没有提到第一行

UIWindowScene *winScreen = (UIWindowScene *)scene;

此代码应添加到 SceneDelegate.m 文件中 现在我们可以删除 main.storyboard 文件,删除此文件后,我们还必须从 info.plist 中删除两个引用

in project configuration > Info tab > delete Main screen interface file base name
also in project configuration > Info tab > Application scene manifest > Scene configuration > Application session role > Item 0 > delete Storyboard name

引用要删除的引用的图像

注意:当我发布此答案时,此方法现在有效,但随着新版本的发布,将来可能不起作用,因此请不断更新自己。

评论

0赞 3/31/2023
这并不能真正回答这个问题。如果您有其他问题,可以通过单击“提问”来提问。要在此问题获得新答案时收到通知,您可以关注此问题。一旦你有足够的声誉,你还可以添加赏金来吸引更多人关注这个问题。- 从评论