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

时间:2012-05-03 09:29:51

标签: ios objective-c swift uiviewcontroller uistoryboard

如何以编程方式为Storyboard设置InitialViewController?我希望将故事板打开到不同的视图,具体取决于从发布到发布可能有所不同的某些条件。

24 个答案:

答案 0 :(得分:452)

如何没有虚拟初始视图控制器

确保所有初始视图控制器都具有故事板ID。

在故事板中,取消选中第一个视图控制器中的“是初始视图控制器”属性。

如果此时运行您的应用,您会看到:

Failed to instantiate the default view controller for UIMainStoryboardFile 'MainStoryboard' - perhaps the designated entry point is not set?

您会注意到app delegate中的窗口属性现在为零。

在应用的设置中,转到目标和Info标签。清楚Main storyboard file base name的价值。在General标签上,清除Main Interface的值。这将删除警告。

在app delegate的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;
}

答案 1 :(得分:115)

对于所有 Swift 爱好者,这里的答案是 @Travis 翻译成 SWIFT

在Objective C代码之前解释 @Travis 。然后,

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. 根据它的故事板ID
  4. 实例化我们的新初始视图控制器
  5. 将我们新窗口的根视图控制器设置为我们刚刚启动的新控制器
  6. 让我们的新窗口可见
  7. 享受快乐的节目!

答案 2 :(得分:45)

您可以在(BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions

中以编程方式设置关键窗口的rootViewController

例如:

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

答案 3 :(得分:12)

SWIFT 5

如果在故事板上没有将ViewController设置为初始ViewController,则需要做两件事:

  1. 转到项目TARGETS,选择项目->常规->清除“主界面”字段。
  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 :(得分:12)

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

答案 5 :(得分:9)

您可以将Navigation 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];
}

由于

答案 6 :(得分:6)

打开mainstoryboard,选择您想先启动的视图,然后打开Utilities - &gt;属性。在“View Controller”下方,您会看到“Is Initial View Controller”单选按钮。只需选择它。

---修改后的问题:

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

答案 7 :(得分:2)

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

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

当然,您需要根据您选择适当视图控制器的标准来实现逻辑。

另外,不要忘记添加标识(选择故事板 - &gt;控制器场景 - &gt;显示标识检查器 - &gt;分配StorboardID)。

答案 8 :(得分:2)

针对iOS 13和场景委托的更新的答案:

确保在info.plist文件中进入“应用程序场景清单”->“场景配置”->“应用程序会话角色”->“项目0”,并在那里删除对主故事板的引用。否则,您将收到有关无法从情节提要实例化的相同警告。

还将代码从应用程序委托移至场景委托方法scene(_:willConnectTo:options :),因为这是现在处理生命周期事件的地方。

答案 9 :(得分:2)

使用 Swift 3 Swift 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
}

答案 10 :(得分:2)

我创建了一个路由类来处理动态导航并保持干净的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!)

答案 11 :(得分:2)

您可以使用Interface Builder以及以编程方式设置initial view controller

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

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

Swift:

        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

答案 12 :(得分:2)

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

答案 13 :(得分:1)

Swift 5或更高版本#通过此简单代码即可制作路径视图控制器。 如果您使用的是xcode 11或更高版本,请在AppDelegate中首先初始化var xmlrpc = require('xmlrpc'); var client = xmlrpc.createClient({ host: 'xyz.com', port: 1234, path:'/dummy' }); for(let i=0; i<DynamicLength; i++) { client.methodCall(ProcedureName, Parameter[i] , Callback(error, result){ console.log(result) }); }

var window: UIWindow?

答案 14 :(得分:1)

如果您不想更改applicationDidFinish,则可以执行以下操作:

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

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

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

}

答案 15 :(得分:0)

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

self.window.rootViewController = rootVC;

in

- (BOOL) application:didFinishLaunchingWithOptions:

答案 16 :(得分:0)

感谢在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()
    }

答案 17 :(得分:0)

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),否则它只是呈现新的视图控制器你可能

答案 18 :(得分:0)

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
}

答案 19 :(得分:0)

 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**

答案 20 :(得分:0)

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

答案 21 :(得分:0)

Xcode 12.4 Swift 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()
}

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

答案 22 :(得分:0)

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

[Swift 5 and 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
    }
}

答案 23 :(得分:-3)

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

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