提问人:Jagdev Sendhav 提问时间:5/3/2012 最后编辑:CœurJagdev Sendhav 更新时间:3/27/2023 访问量:168527
使用 Storyboard 以编程方式设置初始视图控制器
Programmatically set the initial view controller using Storyboards
问:
如何以编程方式设置 Storyboard?我想根据某些条件打开我的故事板以显示不同的视图,这些条件可能因启动而异。InitialViewController
答:
选择要首先打开的视图控制器,然后转到属性检查器。 转到初始场景并选中初始视图控制器选项。
现在,这将是您的初始视图控制器,它将在应用程序启动时首先打开。
打开主情节提要,选择要首先启动的视图,然后打开“实用工具”-“>属性”。在“视图控制器”下方,您会看到“是初始视图控制器”单选按钮。只需选择它。
--- 对经修订的问题:
也许你可以试试这个:在初始视图的 ViewDidLoad 部分中编写一个方法,当该方法在应用程序启动时运行时,该方法会触发到另一个视图的 segue。
评论
我认为这是不可能的。 相反,你可以有一个初始控制器,它将具有与不同视图控制器的顺序。在启动时,您可以决定以编程方式执行哪个 segue。
如何在没有虚拟初始视图控制器的情况下使用
确保所有初始视图控制器都具有 Storyboard ID。
在情节提要中,取消选中第一个视图控制器中的“是初始视图控制器”属性。
如果此时运行应用,你将阅读:
无法实例化 UIMainStoryboardFile 'MainStoryboard' 的默认视图控制器 - 可能未设置指定的入口点?
你会注意到,应用委托中的 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;
}
评论
didFinishLaunchingWithOptions
self.window = UIWindow(frame: UIScreen.mainScreen().bounds) var storyboard = UIStoryboard(name: "Main", bundle: nil) var viewController: UIViewController = // self.window!.rootViewController = viewController self.window!.makeKeyAndVisible()
您可以通过编程方式将键窗口的 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;
}
评论
init()
deinit()
viewDidLoad()
IBOutlet
几天前,我遇到了同样的情况。一个非常简单的技巧解决了这个问题。 我在 launch2 之前设置了隐藏我的初始视图控制器。如果初始视图控制器是正确的控制器,则在 viewDidLoad 中将其设置为可见。否则,将对所需的视图控制器执行 segue。它在 iOS 6.1 及更高版本中完美运行。我敢肯定它适用于早期版本的 iOS。
对于所有 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
步骤说明:
- 创建一个具有当前窗口大小的新窗口,并将其设置为我们的主窗口
- 实例化一个故事板,我们可以用它来创建新的初始视图控制器
- 根据其 Storyboard ID 实例化新的初始视图控制器
- 将新窗口的根视图控制器设置为我们刚刚启动的新控制器
- 使我们的新窗口可见
享受和快乐的编程!
评论
您可以将导航 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];
}
谢谢
您可以使用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
谢谢在 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:
评论
rootVC
instantiateViewControllerWithIdentifier
斯威夫特 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()
当然,您需要实现您的逻辑,根据哪些条件选择合适的视图控制器。
此外,不要忘记添加标识(选择“情节提要”->“控制器场景”-“>”显示标识检查器“>分配 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!)
使用 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
}
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),否则它只是存在新的视图控制器,这可能是
评论
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**
评论
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()
斯威夫特 5
如果没有在情节提要中将 ViewController 设置为初始 ViewController,则需要执行 2 项操作:
- 转到您的项目 TARGETS,选择您的项目 -> 常规 -> 清除 Main Interface 字段。
- 始终在项目 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()
}
评论
Failed to instantiate the default view controller for UIMainStoryboardFile 'Main' - perhaps the designated entry point is not set
UIWindow(windowScene: windowScene)
initWithFrame:
如果您在 iOS 13+ 中使用场景委托:
确保在文件中找到以下行:Info.plist
Application Scene Manifest > Scene Configuration > Application Session Role > Item 0
并在此处删除对主情节提要的引用。否则,你将收到相同的警告,提示无法从 Storyboard 实例化。
此外,将代码从 app delegate 移动到 scene delegate 方法 ,因为这是现在处理生命周期事件的地方。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 斯威夫特 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()
}
您可以添加视图控制器场景将显示的条件
使用 Storyboards(而不是 Main)设置初始 ViewController
Main.storyboard
->视图控制器 ->属性检查器 ->取消选中Is Initial View Controller
应用目标 -> 常规 ->全部删除
Main Interface
编辑应用委托
@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
}
}
以下代码是目标 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
注意:当我发布此答案时,此方法现在有效,但随着新版本的发布,将来可能不起作用,因此请不断更新自己。
评论