Using Multiple Storyboards in iOS

∥☆過路亽.° 提交于 2019-12-27 12:08:17

问题


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:

  • http://www.box.com/s/njnyzjoqg8pnqofv838m
  • http://www.box.com/s/8dqygclmp5ic86e47bi5
  • http://www.box.com/s/k7foe7gpgh2rs3y8gqxd
  • http://www.box.com/s/rym111x7xqxqao51ruip

回答1:


These are the best articles I've seen on multiple storyboards.

  • Storyboard best practices
  • Linking storyboards with segues

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




回答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.




回答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.




回答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.




回答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).




回答6:


Apple's docs say that you may have multiple storyboards. Unfortunately they don't go into any real detail on how to do that. As you've found out, Interface Builder won't help you, so you'll have to do it in code. It works much like loading XIBs:

[UIStoryboard storyboardWithName:@”MyNewStoryboard” bundle:myBundle]

Having said that, if you don't "want one big/bloated storyboard" as you said in your comment then XIBs really are the way to go. That 'bigness' is the benefit: all the transitions between VCs are laid out in one place. Having multiple storyboards is really so that you can support multiple different and unrelated flows through your app: for example, one storyboard for a complex configuration flow and another one for the main user flow.




回答7:


I've found that if you have a named segue in a second storyboard that you want to use in a call to performSegueWithIdenitfier: you must set the "Storyboard ID" field in the "Identity" tab on the source ViewController.

For example if you gave a VC called "ViewController1" with a segue called "segue1" to another VC, set the "Storyboard ID" of "ViewController1" to whatever (say "viewC1" or something) and then in ViewController1.m you can use [self performSegueWithIdentifier:@"segue1" sender:self].




回答8:


Xcode 8.2.1

You can reference a view controller in an external storyboard.

drag a connection from the UITabBarController to the external Storyboard Reference, add it as a "view controllers" relationship. In the main storyboard it shows as "Item/square", but in the external storyboard you should add a UITabBarItem and define the name and image/s for the tab.

Attributes inspector when the Storyboard Reference is selected.

You will also need to give the external controller a "Storyboard ID" in its storyboard (not shown here), and reference it's name in the reference.




回答9:


Follow below steps to achieve this task:

Step 1 : Search for an Storyboard Reference in components (Refer Screen Shot)

Step 2 : Select new storyboard reference. (Refer Screen Shot)

Step 3: Provide new storyboard name and identifier of initial view controller's identifier (Refer Screen Shot)

Build and Run. It will Work.



来源:https://stackoverflow.com/questions/8297701/using-multiple-storyboards-in-ios

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!