Using Multiple Storyboards with a Tabbarcontroller

UITabBarController with multiple storyboards

If your target is iOS 9 and above, you should create storyboard references for the view controllers you want to include in another storyboard. Here's how it works:

  1. Create a second storyboard, move the desired view controller into it and give it a Storyboard ID under the Identity inspector.

Identity inspector


  1. Go to your first storyboard and search for Storyboard Reference in the Object library.

Object library - Storyboard Reference


  1. Drag it into your storyboard and create a "view controllers" relationship with the tab bar controller just like you would with a view controller.

tab bar controller with view controllers in the storyboard


  1. Under the Storyboard Reference's Attribute inspector, change your settings accordingly. For Referenced ID, use the view controller's ID on the second view controller.

the Storyboard Reference's Attribute inspector

Swift 3+: Multiple Storyboards with TabBarController. Set TabBarController Tab, Segue to desired ViewController

Swift 3+
I’d be surprised if this is the best answer but this is the only solution that worked. A bit of my problem stemmed from lack of understanding. But the concept I arrived at was to separate the functions into two parts. Setting the tabbarcontroller tab, then segueing to the destination using a variable struct.
I ended up setting a struct at Point A.

struct Destination {
static var currentID = Int()
}

And on button press I would set the variable with this and then and call the function below:

Destination.currentID = currentID
goToViewControllerA()

Then using part of the code I had before I could set the tabbar Controller as the root view controller and go to ViewControllerA (the first view controller) on the selected tab. This is done in an uiviewcontroller extension but can also be done in a function in Point A.

goToViewControllerA(){
let tab = 2
let sbOne = UIStoryboard(name: "Main", bundle: nil)
let tabBarController = sbOne.instantiateViewController(withIdentifier: "TabBarController") as! UITabBarController
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window?.rootViewController = tabBarController
tabBarController.selectedIndex = tab
}

It’s then just a matter of checking if the struct static var is set, and segueing to the destination controller (ViewControllerB). This is done in ViewControllerA, or if you have to segue through multiple view controllers you could model your function on each viewcontroller using this in the viewdidload.

If Destination.currentID != Int() {
performSegue(withIdentifier:“toViewControllerBSegue”, sender:self)
}

I’d love to learn a better way of doing this if it exists.

TWO StoryBoards, ONE Tab Bar Controller

Ad. 4

If you want to set properly icon you should:

  1. At start attach new UIViewController by storyboard to your UITabBarController.
  2. Set proper icon for this tab.
  3. Remove connection.
  4. Copy and pase this controller to the second storyboard and set it as initial view controller.

Or just add button programically (XML code):

    <!--Settings-->
<scene sceneID="Cac-NB-uhR">
<objects>
<navigationController definesPresentationContext="YES" id="BkC-WO-8Bx" sceneMemberID="viewController">
<tabBarItem key="tabBarItem" title="Settings" image="icoAxis" id="PEg-DC-QVf"/>
<navigationBar key="navigationBar" contentMode="scaleToFill" id="4RT-g8-Hp3">
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<connections>
<segue destination="bvJ-l1-eMt" kind="relationship" relationship="rootViewController" id="FJJ-h4-ftX"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Ane-ce-dgm" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="947" y="1037"/>
</scene>

At start i got my Navigation controller in main.storyboard. Now in derived from UITabBarViewController:

- (void)viewDidLoad {
[super viewDidLoad];
UIStoryboard *settingsStoryboard = [StoryboardManager getSettingsStoryboard];
UINavigationController *navigationController = [settingsStoryboard instantiateInitialViewController];

NSMutableArray *arr = [self.viewControllers mutableCopy];
[arr addObject:navigationController];
[self setViewControllers:arr];
}

EDIT

Answering to your other questions:

Ad 1.

Is this a good practice?
Yes it is. If you are using storyboards in your project and your project reachs tens of view controllers kept in one storyboard may cause:

  1. The storyboard will open very slowly e.g. 10 seconds. It really iritates developer.
  2. Merge conflicts when many developers would add/modify/delete controller in that storyboard.
  3. Sometimes happen critical problem with storyboard and editor may not able to open it. In some cases you may be forced to revert the changes in the storyboard. Using multiple storyboards decrease the chance that you may loose done changes.

Ad 2.

Do you see anything unsave in the code?
Your code looks fine. The only thing that may worry me is that you use name of the storyboard directly. If you use settings in more than one place you should "pack" getting controller in separate method/class. The problem may occur if you will rename storyboard name - then you will have to find all occurances to change them. If you will miss one of them, then some problems may occur. Anyway I don't think extracting that methos is obligatory.

Ad 3.

Can you forsee any errors down the road?
I don't see any problems that may happen.

UITabBarController with diffent storyboard file for each ViewController of the TabBar

You're kind of missing out on the point of storyboards, which is to let you see the structure of the app and relationships between view controllers.

It sounds like you're not getting a lot of benefit from using a storyboard for the tab bar controller, so it might make sense to set that up programmatically, which lets you instantiate each of the view controllers yourself using separate storyboards.

Alternatively, you could include the tab bar controller, any necessary navigation controllers, and the root controller for each nav controller in one storyboard, and then have each of those root controllers load subsequent view controllers from other storyboards.

Two storyboards, both contain TabBarControllers. How to segue between them?

What you're asking to do is perfectly legal and easy. Simple do a present / modal segue from one UITabBarController to the other. This will completely replace the interface (the first tab bar controller and its tab bar) with a new interface (the second tab bar controller and its tab bar).

How to programatically make tab bar which presents new storyboards?

Create a UIStoryboard and instantiate the initial view controller:

UIStoryboard(name: "TabOneStoryboard", bundle: nil)
.instantiateInitialViewController() as! TabOneViewController

If you don't want to instantiate the initial view controller then create it via id:

UIStoryboard(name: "TabOneStoryboard", bundle: nil)
.instantiateViewController(withIdentifier: "TabOneViewControllerID") as! TabOneViewController

Remember to set the initial view controller in the storyboard's Attributes Inspector: Attribute inspector

I feel that this is a very practical approach for reducing the size of storyboards. After the view controllers are built, they should be cached with the UITabBarController. Don't worry about performance of the storyboard loading unless you see something get slow. Apple is pretty good about cleanup and performance with these things.

This post addresses that problem a bit: Multiple storyboards: should I use a singleton pattern to cache them?



Related Topics



Leave a reply



Submit