删除Main Storyboard后设置UITabBarController为根控制器时出现找不到故事板错误
问题描述
我决定纯用UIKit开发项目,因此删除了Main storyboard,也移除了Info.plist中「Storyboard name」和「Main storyboard file base name」的配置,并修改了SceneDelegate。目前单个ViewController可以正常显示,但尝试设置UITabBarController为根控制器时,出现以下错误:
错误信息
Thread 1: "Could not find a storyboard named 'Main' in bundle NSBundle </Users/[MyDesktopName]/Library/Developer/CoreSimulator/Devices/[ApplicationName]/data/Containers/Bundle/Application/[ApplicationName]/BTY.app> (loaded)"
当前相关代码
BackgroundViewController(原根控制器)
import UIKit class BackgroundViewController: UIViewController { let backgroundTabBarController = UITabBarController() override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .white createTabBar() } } extension BackgroundViewController { private func createTabBar() { view.backgroundColor = .white view.addSubview(backgroundTabBarController.view) let firstViewController = BookSearchViewController() let secondViewController = MainViewController() let thirdViewController = UserStatusViewController() let lastViewController = OrderViewController() firstViewController.tabBarItem = UITabBarItem(title: "Search", image: UIImage(systemName: "magnifyingglass.circle.fill"), selectedImage: UIImage(systemName: "magnifyingglass.circle")) // firstViewController.tabBarItem.tag = 0 secondViewController.tabBarItem = UITabBarItem(title: "Main", image: UIImage(systemName: "house.fill"), selectedImage: UIImage(systemName: "house")) // secondViewController.tabBarItem.tag = 1 thirdViewController.tabBarItem = UITabBarItem(title: "My", image: UIImage(systemName: "person.fill"), selectedImage: UIImage(systemName: "person")) // thirdViewController.tabBarItem.tag = 2 lastViewController.tabBarItem = UITabBarItem(title: "Order", image: UIImage(systemName: "menucard.fill"), selectedImage: UIImage(systemName: "menucard")) // lastViewController.tabBarItem.tag = 3 backgroundTabBarController.viewControllers = [firstViewController, secondViewController, thirdViewController, lastViewController] backgroundTabBarController.selectedViewController = secondViewController } }
SceneDelegate
import UIKit class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let windowScene = (scene as? UIWindowScene) else { return } window = UIWindow(windowScene: windowScene) window?.rootViewController = BackgroundViewController() window?.makeKeyAndVisible() } }
已尝试的解决方法
- 在SceneDelegate中直接创建UITabBarController并设为根控制器
- 创建包含UITabBarController的新UIViewController作为根控制器
- 使用
UINavigationController(rootViewController:)包裹视图控制器 - 从其他ViewController中Present UITabBarController
正确实现方案
1. 彻底清理Info.plist配置
检查并确保Info.plist中所有与storyboard相关的配置项已完全移除:
- 删除
Main storyboard file base name键 - 进入
Application Scene Manifest->Scene Configuration->Default Configuration,删除Storyboard Name键
2. 确保所有子ViewController为纯代码初始化
每个自定义ViewController(如BookSearchViewController、MainViewController等)都需要重写初始化方法,避免尝试从storyboard/nib加载:
import UIKit class MainViewController: UIViewController { override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { super.init(nibName: nil, bundle: nil) view.backgroundColor = .white // 初始化视图背景色 } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") // 纯代码开发无需实现该方法 } override func viewDidLoad() { super.viewDidLoad() // 这里添加视图逻辑 } }
其他几个子ViewController需要做同样的修改。
3. 直接在SceneDelegate中配置并设置UITabBarController为根控制器
无需用额外的BackgroundViewController包裹,直接在SceneDelegate中完成UITabBarController的配置:
import UIKit class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let windowScene = (scene as? UIWindowScene) else { return } window = UIWindow(windowScene: windowScene) // 创建UITabBarController let tabBarController = UITabBarController() // 初始化子控制器 let searchVC = BookSearchViewController() let mainVC = MainViewController() let userVC = UserStatusViewController() let orderVC = OrderViewController() // 设置TabBarItem searchVC.tabBarItem = UITabBarItem(title: "搜索", image: UIImage(systemName: "magnifyingglass.circle.fill"), selectedImage: UIImage(systemName: "magnifyingglass.circle")) mainVC.tabBarItem = UITabBarItem(title: "首页", image: UIImage(systemName: "house.fill"), selectedImage: UIImage(systemName: "house")) userVC.tabBarItem = UITabBarItem(title: "我的", image: UIImage(systemName: "person.fill"), selectedImage: UIImage(systemName: "person")) orderVC.tabBarItem = UITabBarItem(title: "订单", image: UIImage(systemName: "menucard.fill"), selectedImage: UIImage(systemName: "menucard")) // 关联子控制器到TabBar tabBarController.viewControllers = [searchVC, mainVC, userVC, orderVC] tabBarController.selectedViewController = mainVC // 默认选中首页 // 设置为根控制器 window?.rootViewController = tabBarController window?.makeKeyAndVisible() } }
错误原因分析
出现找不到Main storyboard的错误,核心原因是:
- 某个子ViewController在初始化时,默认尝试通过
init?(coder:)方法从storyboard加载(比如这些VC之前是在Main.storyboard中创建的,即使删除了storyboard,代码中仍残留了依赖storyboard的初始化逻辑) - Info.plist中可能还有未清理干净的storyboard配置项
内容的提问来源于stack exchange,提问作者Rolf.J
相关产品推荐
相关产品推荐

