在iOS中使用多个情节提要


78

我的目标是创建一个选项卡式应用程序,然后将每个选项卡的视图构建在单独的故事板上。

故事板截图

我的主板是一个选项卡视图。

然后,我使用2个View Controller创建一个辅助情节提要板(storyboard#2)。第一个视图控制器(也被选中为初始视图)具有一个按钮,并选择(模式)到第二个视图。第一视图控制器

我设法通过继承和覆盖Storyboard#2的loadView来加载视图。 loadView覆盖

这是模拟器的输出。

仿真器

当点击“点击我”按钮时,我得到一个EXC_BAD_ACCESS。segue不起作用,似乎第二个故事板没有完全加载。

有人尝试过这样做并使其正常工作吗?有一个来自SkillMaster.net的youtube视频,但他没有演示次要故事情节下segue是否起作用。视频在这里:http: //youtu.be/D4_twoYvB4M

感谢您的输入和帮助!

屏幕截图:


20
我不确定这是否不是一个好的做法,但我想:1.没有一个大的/ blo肿的故事板2.难以合并代码(我们很少有编码人员在工作和提交)
Daddycat Tan Yin请参阅

也许您可以尝试简单地使用我们在iOS5之前使用的.xib文件?将它们与情节提要结合起来应该不会太难。
汤姆·范德·沃尔德

我想知道我们是否可以使用Storyboard来做到这一点。XIB肯定会工作。
Daddycat Tan Yin请参阅

5
大型合并冲突友好的XML文件拆分思路+1000
Pierre de LESPINAY 2014年

构建产品线时,可以使用多个情节提要,而不是单个产品。在这种情况下,您有一个用于核心/
原始

Answers:


82

这些是我在多个故事板上看到的最好的文章。

这个家伙不仅告诉您如何用代码创建新的故事板,而且

  • 建议在实践中使用多个情节提要(更多模块化代码)
  • 讨论何时使用Xibs和Storyboard(XIB保留视图,Storboard基于控制器)
  • 在github上提供了一个将故事板与segues链接的类

请注意,这最后一点很重要,因为多个情节提要的关键缺点是您通常无法将它们与segues链接起来,但是robs库允许您稍作改动

另请参阅此处讨论


44

OP编辑了他的问题,以包括答案:

UIStoryboard* storyboard = [UIStoryboard storyboardWithName:@"HelpStoryboard" bundle:nil];
UIViewController* initialHelpView = [storyboard instantiateInitialViewController];

initialHelpView.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:initialHelpView animated:YES];

当然,从何处调用它是有意义的,因为您可能有2个情节提要板及其视图堆栈在内存中。因此,最好是从另一个情节提要的视图控制器外部调用此代码。


2
该问题已从SO中删除:-(.。无论如何,您认为应将此片段放在该用例中吗?我正面临着相同的情况,而我真的看不到我可以在哪里UITabbarController进行实例化每个选项卡上正确的情节tabBarController:shouldSelectViewController:
提要

2
我正在使用上述方法,但没有使用标签栏。我将此代码放入按钮选择器指定的操作方法中。基本上,代码与在将定格场景转移到其自己的故事板之前在prepareForSegue中使用的代码相同。最初我犯的一个错误是,我的新情节提要板的主视图嵌入在UINavigationController中-设置好后,我尝试呈现该视图而不是nav控制器。
大黄2012年

19

我研究了大黄建议的RBStoryboardLink方法。该实现替代了看起来很奇怪的视图控制器的属性。我相信我已经找到避免这种情况的方法。这是演示项目

导航控制器

导航控制器可以只将引用的视图控制器设置为根。这种视图控制器的实现可能如下所示:

@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

查看控制器

当您要推送外部情节提要板中定义的视图控制器时,问题就开始了。复制属性时就是这种情况。取而代之的是,我们可以实现自定义segue,它将用外部情节提要中的真实目标控制器代替伪造的目标控制器。

@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用作占位符,并包含替代属性(storyboardName和sceneIdentifier)所需。

@interface ExternViewController : UIViewController

@property (strong, nonatomic) NSString *storyboardName;
@property (strong, nonatomic) NSString *sceneIdentifier;

@end

@implementation ExternViewController

@end

我们需要为占位符视图控制器设置这些属性和自定义类。还将链接视图控制器与ExternStoryboardSegue。

IB屏幕截图


1
我试图通过一种更好的解决方案来改善这一点github.com/jeremygrenier/JGLinkedStoryboard
Jeremy Grenier

16

从我的一个XIB文件中,我导航到GUI的一个更复杂的部分,为此,我正在使用一个Storyboard。因此,我的XIB中的按钮将导航到情节提要。我为此的代码是:

UIStoryboard* storyboard = [UIStoryboard storyboardWithName:@"MyStoryboardIdentifier" bundle:nil];
UIViewController* myStoryBoardInitialViewController = [storyboard instantiateInitialViewController];

[self.navigationController pushViewController:myStoryBoardInitialViewController animated:YES];

这将成功将我的StoryBoard推到视图上。上面的代码从按钮“ Touch Up Inside”操作中调用。


9

从Xcode 7(并移植回iOS8)开始,您现在可以使用情节提要参考。在WWDC 2015会议中提到了这一点(它在第一个小时左右开始谈论它们)。你必须做的基本上都是选择的ViewController你想移动到不同的故事板,并点击的编辑- >重构到故事板...。给它起个名字,瞧:

在此处输入图片说明

请注意,如果您有已移至新情节提要的VC,并且未在其外部引用(应该是),则应从main.storyboard中删除其引用(放宽它们将保留在新创建的情节提要中,您可以仅删除对其的引用)。


7

苹果公司的文档说您可能有多个情节提要。不幸的是,他们没有详细说明如何执行此操作。如您所知,Interface Builder不会为您提供帮助,因此您必须使用代码来完成。它的工作原理类似于加载XIB:

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

话虽如此,如果您不如您在评论中所说的那样“想要一个大的/ blo肿的故事板”,那么XIB确实是您的理想之选。这种“大”是有好处的:VC之间的所有过渡都放在一个地方。拥有多个情节提要实际上是为了让您可以通过您的应用程序支持多个不同且不相关的流程:例如,一个情节提要用于复杂的配置流程,另一个情节提要用于主要用户流程。


25
最大的问题是,当您与3个以上的团队一起工作时,合并单个故事板是一场噩梦。
Brian Liang

2
我可以想象这是一个问题。情节提要板有很多粗糙的边缘;你的观点还多。
蒂姆(Tim)

4
您不必为了避免合并噩梦而放弃情节提要提供的所有舒适感。只需隔离不同的独立区域,然后为每个区域分配一个单独的情节提要。对于所有内部过渡,您仍将拥有情节提要的所有魔力。选项卡式应用程序非常适合这种情况。设置屏幕。即使您是一个开发人员,将故事板拆分成几个独立的部分可能仍然很重要。
KPM 2012年

2

我发现,如果您要在第二个故事板上有一个命名的segue,您想在调用中执行到PerformSegueWithIdenitfier:您必须在源ViewController的“ Identity”选项卡中设置“ Storyboard ID”字段。

例如,如果您给一个名为“ ViewController1”的VC提供了另一个名为“ segue1”的名称给另一个VC,请将“ ViewController1”的“ Storyboard ID”设置为任何值(例如“ viewC1”或类似内容),然后在ViewController1.m中可以使用[self performSegueWithIdentifier:@“ segue1”发送者:自我]。


2

Xcode 8.2.1

您可以在外部情节提要中引用视图控制器。

从TabBarController到Storyboard参考的关系

将一个连接从拖动UITabBarController到外部Storyboard Reference,将其添加为“视图控制器”关系。在主情节提要中,它显示为“项目/正方形”,但在外部情节提要中,您应添加UITabBarItem并定义选项卡的名称和图像。

在此处输入图片说明

Storyboard Reference选择时的属性检查器。

您还需要在其情节提要中为外部控制器提供一个“ Storyboard ID” (此处未显示),并在参考中引用其名称。


1

请按照以下步骤完成此任务:

步骤1:搜索Storyboard Referencein组件(请参阅截屏)

步骤2:选择新的情节提要参考。(请参阅屏幕截图)

步骤3:提供新的故事板名称和初始视图控制器的标识符的标识符(请参阅截屏)

在此处输入图片说明

生成并运行。它会工作。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.