Using Multiple Storyboards in iOS
Solution 1
These are the best articles I've seen on multiple storyboards.
Not only does this guy tell you how to create a new storyboard in code, he
- recommends multiple storyboards in practice (more modular code)
- discusses when to use xibs vs storyboards (xibs hold views, storboards are based on controllers)
- provides a class for linking storyboards with segues on github
Note that this last point is important because the key downside of multiple storyboards is that you can't usually link them with segues, but robs library allows that with a bit of fudging
Also see the discussed here
Solution 2
The OP edited his question to include the answer:
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:@"HelpStoryboard" bundle:nil];
UIViewController* initialHelpView = [storyboard instantiateInitialViewController];
initialHelpView.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:initialHelpView animated:YES];
Of course, where you call this from is meaningful, because you might have 2 storyboards and their view stack in memory. So probably best if you call this code from outside the other storyboard's view controllers.
Solution 3
I've examined the RBStoryboardLink approach suggested by Rhubarb. This implementation substitutes view controller's properties which looks odd. I believe I've found the way to avoid this. Here is the demo project.
Navigation controllers
Navigation controllers could just set a referenced view controller as a root. Implementation of such view controller may look like this:
@interface ExternNavigationController : UINavigationController
@property (strong, nonatomic) NSString *storyboardName;
@property (strong, nonatomic) NSString *sceneIdentifier;
@end
@implementation ExternNavigationController
- (void)awakeFromNib
{
NSAssert(self.storyboardName, @"storyboardName is required");
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:self.storyboardName bundle:nil];
UIViewController *vc = self.sceneIdentifier
? [storyboard instantiateViewControllerWithIdentifier:self.sceneIdentifier]
: [storyboard instantiateInitialViewController];
self.viewControllers = @[vc];
}
@end
View controllers
Problems begin when you want to push a view controller defined in an external storyboard. This is the case when properties are copied. Instead of this, we can implement a custom segue which will substitute a fake destination controller with a real one from external storyboard.
@interface ExternStoryboardSegue : UIStoryboardSegue
@end
@implementation ExternStoryboardSegue
- (id)initWithIdentifier:(NSString *)identifier source:(UIViewController *)source destination:(ExternViewController *)destination
{
NSAssert(destination.storyboardName, @"storyboardName is required");
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:destination.storyboardName bundle:nil];
UIViewController *vc = destination.sceneIdentifier
? [storyboard instantiateViewControllerWithIdentifier:destination.sceneIdentifier]
: [storyboard instantiateInitialViewController];
return [super initWithIdentifier:identifier source:source destination:vc];
}
- (void)perform
{
[[self.sourceViewController navigationController] pushViewController:self.destinationViewController animated:YES];
}
@end
ExternViewController is used as a placeholder and contains required for substitution properties (storyboardName and sceneIdentifier).
@interface ExternViewController : UIViewController
@property (strong, nonatomic) NSString *storyboardName;
@property (strong, nonatomic) NSString *sceneIdentifier;
@end
@implementation ExternViewController
@end
We need to set these properties and custom class for placeholder view controller. And also link view controller with ExternStoryboardSegue.
Solution 4
From one of my XIB files I am navigating into a more complicated part of the GUI, and for this part I am using a Storyboard. So a button in my XIB will navigate to the storyboard. The code I have for this is:
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:@"MyStoryboardIdentifier" bundle:nil];
UIViewController* myStoryBoardInitialViewController = [storyboard instantiateInitialViewController];
[self.navigationController pushViewController:myStoryBoardInitialViewController animated:YES];
This will successfully push my StoryBoard onto the view. The code above is called from a buttons "Touch Up Inside" action.
Solution 5
As from Xcode 7(and ported back to iOS8) you can now have storyboard references. It was mentioned in this WWDC 2015 session(it starts talking about them around first hour). Basically all you had to do is select ViewController's which you wish to move to separate storyboard, and click on Editor->Refactor to Storyboard.... Give it a name and voila:
Please note that if you had VC's which are moved to the new storyboard, and are not referenced outside of it(what it should be), you should delete their references from main.storyboard(relax they will remain in newly created storyboard, you are deleting only references to them).
Related videos on Youtube
Daddycat Tan Yin See
Updated on July 05, 2022Comments
-
Daddycat Tan Yin See almost 2 years
My objective is to create a tabbed application, then the view for each of the tabs are constructed in separate storyboards.
My mainstoryboard is a tab view.
Then I create a secondary storyboard (storyboard#2) with 2 View Controllers. The first view controller (also ticked as initial) have a button, and segue (modal) to 2nd view.
I managed to load the view by subclassing and overriding loadView from storyboard#2.
Here's the simulator output.
When click on the "click me" button, I get a
EXC_BAD_ACCESS
. The segue does not work, seems like the second storyboard is not being loaded completely.Has anyone tried to do this before and get it working? There's a youtube video from SkillMaster.net but he does not demonstrate if a segue is working under the secondary storyboard. the video is here: http://youtu.be/D4_twoYvB4M
Thanks for any input and help!
Screenshots:
-
Daddycat Tan Yin See over 12 yearsi am not sure if this is a good practice neither, but i want to: 1. NOT having one big/bloated storyboard 2. difficult to merge code (we have few coders working and commit)
-
Tom van der Woerdt over 12 yearsMaybe you could try simply using the .xib files we used pre-iOS5? They shouldn't be too hard to combine with storyboards.
-
Daddycat Tan Yin See over 12 yearsi would like to know if we can use Storyboard to do this. XIB will definitely work.
-
Pierre de LESPINAY almost 10 years+1000 for the big merge conflict friendly XML file split idea
-
Kirill Gamazkov over 9 yearsSeveral storyboards can make sense when you're building a product line, not the single product. In this case, you have one storyboard for core/vanilla product and one storyboard for each customized product
-
Jeremy Grenier over 9 yearsI tried to improve that with a better solution github.com/jeremygrenier/JGLinkedStoryboard
-
-
Brian Liang over 12 yearsThe biggest issue is when you are working on a team of 3+ where merging a single storyboard is a nightmare.
-
Tim over 12 yearsI can imagine that's a problem. There are quite a few rough edges with storyboards; your point is one more.
-
Jean-Denis Muys over 12 yearsthat question was removed from SO :-(. In any case, where do you think you would put this snippet in this use case? I am facing the same situation, and I can't really see where I could hook up with
UITabbarController
to instantiate the correct storyboard for each tab. Would the delegatetabBarController:shouldSelectViewController:
be appropriate? -
KPM almost 12 yearsYou don't have to drop away all the comfort provided by storyboards just to avoid merging nightmares. Just isolate different independent areas and assign each one a separate storyboard. You'll still have all the magic of the storyboards for all the internal transitions. A tabbed application is a perfect fit for this scenario. A settings screen too. Even if you're a single developer it might still be relevant to split up your storyboard in several independant pieces.
-
Rhubarb over 11 yearsI'm using the above approach but not with a tab bar. I put this code in the action method specified by the selector for the button. Basically the code is the same as I had in prepareForSegue before I moved the segued-to scene into its own storyboard. One mistake I made initially was that my new storyboard had its main view embedded in a UINavigationController - and after setting it up I tried to present the view instead of the nav controller.
-
Jeremy Grenier over 9 yearsI tried to improve that with a better solution github.com/jeremygrenier/JGLinkedStoryboard