137

Is it possible to segue from one storyboard to another, or to embed a storyboard in a view controller in another storyboard? I need to place a UITabBarController in a UINavigationController, and I'd like to keep them nice and separate.

lnafziger
  • 25,760
  • 8
  • 60
  • 101
Ry-
  • 218,210
  • 55
  • 464
  • 476
  • 1
    Look at this answer http://stackoverflow.com/a/19702425/317928 – vokilam Oct 31 '13 at 09:18
  • 5
    Great question. Having one storyboard is a nightmare for team based projects. We regularly break projects into storyboards by "flow" (one storyboard for login, one storyboard for news feed and related screens, etc). It helps minimize the number of merge conflicts, which would otherwise occur every time a developer touches the storyboard. – Brian Sachetta Mar 29 '15 at 15:33
  • @BrianSachetta What else do you do? Any other good similar tips to share? – mfaani Sep 15 '16 at 21:38
  • It depends on your team structure. If you really wanted to, you could have all your user interfaces in separate .xib files. This is how it used to be before storyboards existed. There are plusses and minuses to this approach. The upside is that you'll almost never have conflicts with other developers on the project. The downside is it can be hard to see the app flow visually. – Brian Sachetta Sep 16 '16 at 21:25

6 Answers6

200

Yes, but you have to do it programmatically:

// Get the storyboard named secondStoryBoard from the main bundle:
UIStoryboard *secondStoryBoard = [UIStoryboard storyboardWithName:@"secondStoryBoard" bundle:nil];

// Load the initial view controller from the storyboard.
// Set this by selecting 'Is Initial View Controller' on the appropriate view controller in the storyboard.
UIViewController *theInitialViewController = [secondStoryBoard instantiateInitialViewController];
//
// **OR**  
//
// Load the view controller with the identifier string myTabBar
// Change UIViewController to the appropriate class
UIViewController *theTabBar = (UIViewController *)[secondStoryBoard instantiateViewControllerWithIdentifier:@"myTabBar"];

// Then push the new view controller in the usual way:
[self.navigationController pushViewController:theTabBar animated:YES];
Ry-
  • 218,210
  • 55
  • 464
  • 476
lnafziger
  • 25,760
  • 8
  • 60
  • 101
  • 11
    I just really want to keep the storyboards separate; they're already much too cluttered. – Ry- Mar 14 '12 at 22:29
  • 11
    Just like chapters in a book, I see the need for multiple storyboards. – finneycanhelp Jun 02 '12 at 15:44
  • 48
    When you have multiple developers working on the same application, it becomes very useful to have multiple storyboards because resolving version control conflicts in the storyboard xml is quite painful at times. – Lee Oct 12 '12 at 14:52
  • This doesn't allow you to use custom segues for the transition. – xissburg Jun 13 '14 at 21:51
  • I suspect that in iOS 9 it will become possible to segue from one storyboard to another _automatically_. – matt May 04 '15 at 02:53
  • 14
    In iOS 9 and Xcode 7, cross-storyboard references are now supported. :-) – Quinn Taylor Jun 15 '15 at 15:46
  • Note that if the initial view controller is a navigationcontroller, you need to use `presentViewController` instead of `pushViewController` – sgdesmet Aug 11 '15 at 14:33
  • 1
    See milczi's answer, you can do this now very easily in the UI! – Tim Dec 30 '15 at 00:42
  • 1
    iOS 8 also supports storyboard references. From [Apple's documentation](https://developer.apple.com/library/ios/recipes/xcode_help-IB_storyboard/Chapters/AddSBReference.html): Storyboard references require an app targeting at least iOS 8.0, OS X 10.10, or watchOS 1.0. – user2067021 Mar 29 '16 at 23:46
  • i tried segue identifier in an other storyboard and got the error: doesn't contain a view controller with identifier – user1709076 Jan 06 '17 at 14:27
  • @user1709076 You have to set the identifier by setting the Storyboard ID (in the Storyboard editor) to the same identifier that you are using to reference it in the first line of code. – lnafziger Jan 07 '17 at 15:33
129

From Xcode 7 onwards, you can do this graphically by using a Storyboard Reference:

reference

Add Storyboard Reference to your storyboard. Create segue between ViewController and Storyboard Reference (ctrl + drag)

Then fill this fields.

enter image description here

Where "Tutorial" is "Tutorial.storyboard" file and "MainTutorialController" is your "Storyboard ID" field in ViewControllerSettings

Simon Pickup
  • 832
  • 12
  • 19
milczi
  • 7,064
  • 2
  • 27
  • 22
  • 1
    Good info, however the question is tagged ios5 so this doesn't apply. – lnafziger Feb 08 '16 at 04:57
  • 10
    @Inafziger yes but this question shows up at the top of search results for people using iOS 9 – Brian Ogden Mar 06 '16 at 18:09
  • This is available from XCode 7 onwards. See more info at http://stackoverflow.com/questions/30772145/storyboard-reference-in-xcode-where-should-we-use-it – Simon Pickup Nov 26 '16 at 13:51
  • This worked, but I also need to keep the navigation bar, it is showing without the navigation bar, is there any way to keep a navigation and button to move it back on history, doesn't matter what storyboard it comes from? – Gil Beyruth Feb 23 '17 at 20:11
  • This is working for me in iOS 10. I did note that I need one storyboard reference per segue and couldn't connect multiple segues to one reference point. – Mark Reid Mar 02 '17 at 11:30
  • QUESTION: How do I pass an object forward with this? It isn't working with segue.deastination as! MyViewController – Jude Michael Murphy Aug 03 '17 at 00:47
10

You can't really do segues manually because UIStoryboardSegue is an abstract class. You need to subclass it and implement perform in order for it to do anything. They're really meant to be created in storyboards. You can push the view controller manually, though, which is a good solution. lnafziger's answer does this well:

UIStoryboard *secondStoryBoard = [UIStoryboard storyboardWithName:@"secondStoryBoard" bundle:nil];
UIViewController *theTabBar = [secondStoryBoard instantiateViewControllerWithIdentifier:@"myTabBar"];
[self.navigationController pushViewController:theTabBar animated:YES];

One thing to note, though, is that you've said you want to keep things nice and separate. The idea of storyboards is to allow you to keep things separate while doing all of your design work in one place. Each view controller is nice and separated within the storyboard from the others. The whole idea is to keep it all in one place. Just lay it out nicely so that it's organized, and you'll be good to go. You shouldn't separate it unless you have a really good reason to do so.

lnafziger
  • 25,760
  • 8
  • 60
  • 101
wbyoung
  • 22,383
  • 2
  • 34
  • 40
  • 6
    merging storyboards doesn't work very well, so in a multi-developer-environnment, it could be interesting to use seperate storyboards. Also the performance can get pretty bad in big projects with a single storyboard. – calimarkus Mar 14 '12 at 09:34
  • 1
    We use multiple storyboards, but the point is you can't really do that and segue between them. Apple designed it so you could do everything in one place, so the idea is kind of to use just one (not that you can't). Performance should not be an issue. The storyboard is compiled into separate nib files for each view controller. You should get very good performance from storyboards. The performance will be just as good as if you had separate xibs for every view controller. – wbyoung Mar 14 '12 at 15:06
  • 3
    In my case, the performance problem is usually in Xcode ... Apple's current implementation of the storyboard editor is weak. – Adam Oct 10 '12 at 19:23
  • 1
    A 60-scene Storyboard takes 13 seconds to open on a 2014 Mac Pro. I have filed a radar. – Robert Atkins Dec 10 '14 at 16:26
7

You should not place UITabBarControllers in a UINavigationController. It's asking for bugs such as incorrect autorotation/view unloading etc., as Apple doesn't support this sort of containment:

When combining view controllers, however, the order of containment is important; only certain arrangements are valid. The order of containment, from child to parent, is as follows:

  • Content view controllers, and container view controllers that have flexible bounds (such as the page view controller)
  • Navigation view controller
  • Tab bar controller
  • Split view controller
Danra
  • 9,546
  • 5
  • 59
  • 117
  • 1
    I totally agree, and for multiple reasons. Putting a TabBarController inside of a NavigationController is not a good idea, because the delegates would not fire correctly for the views contained inside them, and the end user will have a terrible time navigating the interface. They would have a hard time getting back to the controller that leads out of the TabBar/Navigation interface. The other way around, is OK, A NavigationController inside a TabBarController. It's always best to not confuse the the end user and listen to Apples suggestions! – Hubert Kunnemeyer Mar 14 '12 at 22:39
  • 1
    And yet the native iPhone Music app does exactly that ("Now Playing" part). – Enzo Tran Jun 11 '13 at 13:34
  • FYI: iPhone music app doesn't have TabbarController in "Now playing" screen. – sanjana Sep 24 '15 at 17:21
4

Here is a swift version:

let targetStoryboardName = "Main"
let targetStoryboard = UIStoryboard(name: targetStoryboardName, bundle: nil)
if let targetViewController = targetStoryboard.instantiateInitialViewController() {
    self.navigationController?.pushViewController(targetViewController, animated: true)
}
DudeOnRock
  • 3,685
  • 3
  • 27
  • 58
-1

did you try the following :

2/ click to select your view controller which is linked to your navigation controller and in top menu : editor -> embed in -> Tab Bar controller

Note : I didn't test it because I'm using the opposite : making tabbed bar apps and puting navigation controller inside).

moxy
  • 1,634
  • 1
  • 11
  • 19