iosstoryboarduitabbarcontroller

How to use UITabBarController with multiple storyboards?


I just created a new project in Xcode. My main storyboard file contained a tab bar controller as initial view and five navigation controllers linked to it (and each of them are linked to a separate view controller). I decided that to increase productivity, I should create a new storyboard file for each of the five parts of the tab bar. I left the tab bar controller in the Main storyboard and moved the rest into their own storyboard files. I linked the tab bar controller to the five navigation controllers using storyboard references and in the Main storyboard, the tab bar displays correct images and titles. However when I run the app on a simulator or device, the tab bar is suddenly invisible. I can still click on the tabs to change which navigation view to display inside the tab bar controller, but it's just not visible. Btw I haven't added any code in the project so far.

I saw multiple tutorials on separate storyboard files with a tab bar controller but they do exactly the same as me. Could not find any information online about this error. It seems like the storyboard references work fine, but they prevent the tab bar from displaying at all. Also, before when everything was in the Main storyboard, it was all working fine. First of all I just want to know if someone else can get this to work. Btw, when looking at the navigation controllers in the separate storyboard files they don't display a tab bar item. It's like the tab bar controller sees the link to the navigation controllers but not the other way around. I don't know if it should be like this or not. I am using Xcode 14.3.1.


Solution

  • Separating code / UI can help with managing projects.

    However, there are quirks, particularly when using multiple storyboards and Storyboard Reference objects. You've managed to hit one :)

    Couple ways to "fix" this...


    Instead of connecting StoryBoard References to your TabBarController, create a custom UITabBarController class and add the tabs dynamically.

    Along these lines:

    struct MyTab {
        var sbName: String = ""
        var vcID: String = ""
        var tabName: String = ""
        var tabImg: String = ""
    }
    
    class MyTabBar: UITabBarController {
        
        override func viewDidLoad() {
            super.viewDidLoad()
            print(self, #function)
    
            let myTabs: [MyTab] = [
                MyTab(sbName: "FirstTabSB", vcID: "FirstNavC", tabName: "First", tabImg: "1.circle"),
                MyTab(sbName: "SecondTabSB", vcID: "SecondNavC", tabName: "Second", tabImg: "2.circle"),
            ]
            
            var vcs: [UIViewController] = []
            
            for (i, tb) in myTabs.enumerated() {
                let sb = UIStoryboard(name: tb.sbName, bundle: nil)
                let vc = sb.instantiateViewController(withIdentifier: tb.vcID)
                let tabItem = UITabBarItem(title: tb.tabName, image: UIImage(systemName: tb.tabImg), tag: i)
                vc.tabBarItem = tabItem
                vcs.append(vc)
            }
            
            self.viewControllers = vcs
        }
        
    }
    

    Next option -- assuming all tabs are navigation controllers (as you stated in your question) -- setup your Main storyboard like this:

    enter image description here

    And have the Initial View Controller in each storyboard be the VC you want as the "root" of each navigation controller.

    Now you can configure your tab items (title / image / etc) as normal


    Next option - add the TabBarItem to the navigation controller in each "tab" storyboard:

    enter image description here

    enter image description here

    enter image description here


    Note that in any of these cases, you will NOT see the tab bar at the bottom of the view controller(s) when working with them in Storyboard. Although you can select it from Simulated Metrics:

    enter image description here