【问题标题】:Using Multiple Storyboards in iOS在 iOS 中使用多个故事板
【发布时间】:2012-01-08 00:31:23
【问题描述】:

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

我的主故事板是一个标签视图。

然后我创建一个带有 2 个视图控制器的辅助情节提要 (storyboard#2)。第一个视图控制器(也打勾作为初始)有一个按钮,并(模态)到第二个视图。

我设法通过子类化和覆盖storyboard#2 中的loadView 来加载视图。

这是模拟器的输出。

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

以前有没有人尝试过这样做并让它发挥作用? SkillMaster.net 上有一个 youtube 视频,但他没有演示 segue 是否在辅助情节提要下工作。视频在这里:http://youtu.be/D4_twoYvB4M

感谢您的任何意见和帮助!

截图:

【问题讨论】:

  • 我不确定这是否也是一个好习惯,但我想:1. 没有一个大/臃肿的故事板 2. 难以合并代码(我们很少有编码人员在工作和提交)
  • 也许您可以尝试简单地使用我们在 iOS5 之前使用的 .xib 文件?与故事板结合起来应该不会太难。
  • 我想知道我们是否可以使用 Storyboard 来做到这一点。 XIB 肯定会起作用。
  • +1000 用于大合并冲突友好的 XML 文件拆分想法
  • 在构建产品线而不是单个产品时,可以使用几个故事板。在这种情况下,您有一个用于核心/普通产品的故事板和一个用于每个定制产品的故事板

标签: ios user-interface ios5 xcode4.2 uistoryboard


【解决方案1】:

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

这个人不仅告诉你如何用代码创建一个新的故事板,他

  • 建议在实践中使用多个故事板(更模块化的代码)
  • 讨论何时使用 xib 与故事板(xib 保存视图,存储板基于控制器)
  • 提供了一个将故事板与segues链接的类on github

请注意,最后一点很重要,因为多个故事板的主要缺点是您通常不能将它们与 segues 链接,但 rob 库允许这样做,但需要一点技巧

另见讨论的here

【讨论】:

    【解决方案2】:

    OP 编辑​​了他的问题以包含答案:

    UIStoryboard* storyboard = [UIStoryboard storyboardWithName:@"HelpStoryboard" bundle:nil];
    UIViewController* initialHelpView = [storyboard instantiateInitialViewController];
    
    initialHelpView.modalPresentationStyle = UIModalPresentationFormSheet;
    [self presentModalViewController:initialHelpView animated:YES];
    

    当然,你从哪里调用它是有意义的,因为你可能有 2 个故事板和它们在内存中的视图堆栈。因此,最好从其他故事板的视图控制器之外调用此代码。

    【讨论】:

    • 该问题已从 SO 中删除 :-(。无论如何,您认为您会将这个 sn-p 放在这个用例中的什么位置?我面临同样的情况,但我不能真的看到我可以在哪里与UITabbarController 挂钩以实例化每个选项卡的正确情节提要。委托tabBarController:shouldSelectViewController: 是否合适?
    • 我正在使用上述方法,但没有使用标签栏。我将此代码放在按钮选择器指定的操作方法中。基本上,代码与我在将 segued-to 场景移动到它自己的故事板之前在 prepareForSegue 中的代码相同。我最初犯的一个错误是我的新故事板的主视图嵌入在 UINavigationController 中 - 设置后我尝试呈现视图而不是导航控制器。
    【解决方案3】:

    我研究了 Rhubarb 建议的 RBStoryboardLink 方法。 这个实现替代了看起来很奇怪的视图控制器的属性。我相信我已经找到了避免这种情况的方法。 Here is the demo project.

    导航控制器

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

    @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 链接起来。

    【讨论】:

    【解决方案4】:

    从我的一个 XIB 文件中,我正在导航到 GUI 的一个更复杂的部分,对于这一部分,我使用了一个故事板。所以我的 XIB 中的一个按钮将导航到情节提要。我的代码是:

    UIStoryboard* storyboard = [UIStoryboard storyboardWithName:@"MyStoryboardIdentifier" bundle:nil];
    UIViewController* myStoryBoardInitialViewController = [storyboard instantiateInitialViewController];
    
    [self.navigationController pushViewController:myStoryBoardInitialViewController animated:YES];
    

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

    【讨论】:

      【解决方案5】:

      从 Xcode 7(并移植回 iOS8)开始,您现在可以拥有情节提要参考。在这个WWDC 2015 会话中提到了它(它在第一个小时左右开始谈论它们)。基本上,您所要做的就是选择您希望移动到单独故事板的 ViewController,然后单击 Editor->Refactor to Storyboard...。给它一个名字,瞧:

      请注意,如果您有 VC 被移到新的故事板,并且没有在它之外引用(应该是什么),您应该从 main.storyboard 中删除它们的引用(放松它们将保留在新创建的故事板中,您只删除对它们的引用)。

      【讨论】:

        【解决方案6】:

        Apple 的文档说您可能有多个故事板。不幸的是,他们没有详细说明如何做到这一点。正如您所发现的,Interface Builder 不会帮助您,因此您必须在代码中完成。它的工作原理很像加载 XIB:

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

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

        【讨论】:

        • 最大的问题是当你在一个 3 人以上的团队中工作时,合并单个故事板是一场噩梦。
        • 我可以想象这是个问题。故事板有很多粗糙的边缘。你的观点是另外一个。
        • 您不必为了避免合并噩梦而放弃故事板提供的所有舒适感。只需隔离不同的独立区域并为每个区域分配一个单独的故事板。对于所有内部过渡,您仍将拥有故事板的所有魔力。选项卡式应用程序非常适合这种情况。还有一个设置屏幕。即使您是单个开发人员,将您的故事板分成几个独立的部分可能仍然是相关的。
        【解决方案7】:

        Xcode 8.2.1

        您可以在外部故事板中引用视图控制器。

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

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

        您还需要在其故事板中为外部控制器提供一个“故事板 ID”(此处未显示),并在参考中引用它的名称。 p>

        【讨论】:

          【解决方案8】:

          我发现,如果您想在调用 performSegueWithIdenitfier 时使用第二个故事板中的命名 segue:您必须在源 ViewController 的“身份”选项卡中设置“故事板 ID”字段。

          例如,如果您将一个名为“ViewController1”的 VC 和一个名为“segue1”的 segue 提供给另一个 VC,请将“ViewController1”的“Storyboard ID”设置为任何值(例如“viewC1”或其他内容),然后在 ViewController1 中。 m 你可以使用 [self performSegueWithIdentifier:@"segue1" sender:self]。

          【讨论】:

            【解决方案9】:

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

            第 1 步:在组件中搜索 Storyboard Reference(请参阅屏幕截图)

            第 2 步:选择新的故事板参考。 (参考屏幕截图)

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

            构建并运行。它会起作用的。

            【讨论】:

              猜你喜欢
              • 2020-08-05
              • 2012-11-24
              • 2012-10-11
              • 1970-01-01
              • 2012-03-08
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-11-16
              相关资源
              最近更新 更多