在 iOS 中使用多个故事板
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8297701/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using Multiple Storyboards in iOS
提问by Daddycat Tan Yin See
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.
我的 mainstoryboard 是一个选项卡视图。
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.
然后我创建了一个带有 2 个视图控制器的辅助故事板 (storyboard#2)。第一个视图控制器(也被标记为初始)有一个按钮,和第二个视图的segue(模态)。
I managed to load the view by subclassing and overriding loadView from storyboard#2.
我设法通过从 storyboard#2 子类化和覆盖 loadView 来加载视图。
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.
当点击“点击我”按钮时,我得到一个EXC_BAD_ACCESS
. segue 不起作用,似乎第二个故事板没有完全加载。
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
有没有人试过这样做并让它工作?有一个来自 SkillMaster.net 的 youtube 视频,但他没有演示 segue 是否在辅助故事板下工作。视频在这里:http: //youtu.be/D4_twoYvB4M
Thanks for any input and help!
感谢您的任何输入和帮助!
Screenshots:
截图:
回答by Rhubarb
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
- 在实践中推荐多个故事板(更模块化的代码)
- 讨论何时使用 xibs 与故事板(xibs 持有视图,storboards 基于控制器)
- 提供了一个类,用于在 github上将 storyboards 与 segues 链接起来
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
请注意,最后一点很重要,因为多个故事板的主要缺点是您通常不能将它们与 segue 链接起来,但是 robs 库允许这样做
Also see the discussed here
另请参阅此处讨论的
回答by pchap10k
The OP edited his question to include the answer:
OP 编辑了他的问题以包含答案:
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.
当然,您从哪里调用它是有意义的,因为您可能有 2 个故事板及其内存中的视图堆栈。因此,如果您从其他故事板的视图控制器外部调用此代码,则可能是最好的。
回答by vokilam
I've examined the RBStoryboardLinkapproach 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.
我检查了大黄建议的RBStoryboardLink方法。这个实现替代了看起来很奇怪的视图控制器的属性。我相信我已经找到了避免这种情况的方法。这是演示项目。
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.
当您想要推送在外部故事板中定义的视图控制器时,问题就开始了。复制属性时就是这种情况。取而代之的是,我们可以实现一个自定义的 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 is used as a placeholder and contains required for substitution properties (storyboardName and sceneIdentifier).
ExternViewController 用作占位符并包含替换属性(storyboardName 和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.
我们需要为占位符视图控制器设置这些属性和自定义类。并且还将视图控制器与 ExternStoryboardSegue 链接起来。
回答by Joachim H. Skeie
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:
从我的一个 XIB 文件中,我导航到 GUI 的一个更复杂的部分,对于这部分,我使用的是 Storyboard。所以我的 XIB 中的一个按钮将导航到故事板。我的代码是:
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.
这将成功地将我的 StoryBoard 推送到视图上。上面的代码是从按钮“Touch Up Inside”操作中调用的。
回答by hris.to
As from Xcode 7(and ported back to iOS8) you can now have storyboard references. It was mentioned in this WWDC 2015session(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:
从 Xcode 7(并移植回 iOS8)开始,您现在可以拥有故事板参考。在WWDC 2015会议中提到了它(它在第一个小时左右开始谈论它们)。基本上,您所要做的就是选择您希望移动到单独故事板的 ViewController,然后单击Editor->Refactor to Storyboard...。给它一个名字,瞧:
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).
请注意,如果您将 VC 移动到新的故事板,并且没有在它之外引用(应该是什么),您应该从 main.storyboard 中删除它们的引用(请放心,它们将保留在新创建的故事板中,您是仅删除对它们的引用)。
回答by Tim
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:
Apple 的文档说您可能有多个故事板。不幸的是,他们没有详细说明如何做到这一点。正如您所发现的,Interface Builder 不会帮助您,因此您必须在代码中完成。它的工作原理很像加载 XIB:
[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.
话虽如此,如果您不希望像您在评论中所说的那样“想要一个大的/臃肿的故事板”,那么 XIB 确实是要走的路。这种“大”就是好处:风投之间的所有转换都集中在一个地方。拥有多个故事板实际上是为了让您可以通过您的应用程序支持多个不同且不相关的流程:例如,一个故事板用于复杂的配置流程,另一个用于主要用户流程。
回答by bshirley
Xcode 8.2.1
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.
将连接从 拖到UITabBarController
外部 Storyboard Reference,将其添加为“视图控制器”关系。在主故事板中,它显示为“项目/方块”,但在外部故事板中,您应该添加一个UITabBarItem
并定义选项卡的名称和图像。
Attributes inspector when the Storyboard Reference
is selected.
Storyboard Reference
选择时的属性检查器。
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.
您还需要在其故事板(此处未显示)中为外部控制器提供一个“故事板 ID”,并在参考中引用它的名称。
回答by nh32rg
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.
我发现,如果您想在第二个故事板中有一个命名的 segue,您想在调用 performSegueWithIdenitfier 时使用它:您必须在源 ViewController 的“身份”选项卡中设置“故事板 ID”字段。
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].
例如,如果您将一个名为“ViewController1”的 VC 和一个名为“segue1”的 segue 提供给另一个 VC,请将“ViewController1”的“故事板 ID”设置为任何内容(例如“viewC1”或其他内容),然后在 ViewController1.m 中您可以使用 [self performSegueWithIdentifier:@"segue1" sender:self]。
回答by Dheeraj D
Follow below steps to achieve this task:
请按照以下步骤完成此任务:
Step 1: Search for an Storyboard Reference
in components (Refer Screen Shot)
第 1 步:搜索Storyboard Reference
in 组件(请参阅屏幕截图)
Step 2: Select new storyboard reference. (Refer Screen Shot)
第 2 步:选择新的故事板参考。(参考屏幕截图)
Step 3: Provide new storyboard name and identifier of initial view controller's identifier (Refer Screen Shot)
第 3 步:提供新的故事板名称和初始视图控制器标识符的标识符(请参阅屏幕截图)
Build and Run. It will Work.
构建和运行。它会工作。