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

如何以编程方式设置Storyboard的InitialViewController ?我想打开我的故事板到一个不同的视图这取决于不同的启动条件。

167364 次浏览
选择你想要首先打开的视图控制器,然后进入属性检查器。 进入初始场景,检查初始视图控制器选项

这是你的初始视图控制器在应用启动时首先打开。

打开mainstoryboard,首先选择要启动的视图,然后打开Utilities—> Attributes。在“视图控制器”下面,你会看到“Is initial View Controller”单选按钮。选择它。

——对修改后的问题:

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

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

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

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

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

如果你运行你的应用程序在这一点你会读:

失败的实例化默认视图控制器UIMainStoryboardFile 'MainStoryboard' -也许指定的入口点没有设置?

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

在应用程序的设置中,转到目标和Info选项卡。这里清除了Main storyboard file base name的值。在General选项卡上,清除Main 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;
}

你可以通过编程方式在(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;
}
几天前我也遇到了同样的情况。一个非常简单的技巧解决了这个问题。 我设置在launch2之前隐藏我的初始视图控制器。如果初始视图控制器是正确的控制器,它在viewDidLoad中被设置为可见。否则,执行一个segue到所需的视图控制器。它在iOS 6.1及以上版本运行良好。我相信它在早期版本的iOS上也能运行

对于所有的斯威夫特爱好者来说,下面是由@Travis翻译成斯威夫特的答案:

做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. 基于Storyboard ID实例化我们新的初始视图控制器
  4. 将新窗口的根视图控制器设置为我们刚刚启动的新控制器
  5. 使新窗口可见

享受和快乐的编程!

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

谢谢

你可以使用接口生成器和编程方式设置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;

迅速:

        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

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

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

self.window.rootViewController = rootVC;

- (BOOL) application:didFinishLaunchingWithOptions:

斯威夫特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
}

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

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

当然,你需要实现你的逻辑,基于什么标准你将选择一个合适的视图控制器。

另外,不要忘记添加一个标识(select storyboard -> Controller Scene -> Show the identity inspector -> assign StorboardID)。

我创建了一个路由类来处理动态导航和保持干净的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斯威夫特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
}
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

另一种方法是present viewController,

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

首先你需要创建storyboard的对象然后改变根(如果需要)然后你引用特定的视图控制器它会被推送当前视图控制器(如果你改变根)否则它会呈现新的视图控制器

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
}
 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**
用下面的简单代码创建路由视图控制器 如果你正在使用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()

斯威夫特5

如果你没有一个ViewController设置为storyboard中的初始ViewController,你需要做两件事:

  1. 进入你的项目TARGETS,选择你的项目-> General ->清除Main Interface字段。
  2. 总是在项目TARGETS中,现在转到Info ->应用场景清单->场景配置->应用程序会话角色-> 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()


}

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

确保在你的Info.plist文件中找到行:

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

并在那里删除对Main Storyboard的引用。否则,您将得到关于从storyboard实例化失败的相同警告。

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

如果你不想改变applicationDidFinish,你可以做下面的技巧:

设置导航控制器为初始视图控制器,并分配给它一个自定义类'MyNavigationController'。然后你可以在viewDidLoad期间调整它的根视图控制器——它会覆盖你在故事板中设置的根视图控制器。

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


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


}

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

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

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

[Swift 5 and Xcode 11]

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

  2. App target ->一般→从Main Interface中删除所有

  3. 编辑App委托

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