【问题标题】:iOS: Best practices for a "one-way" navigation controller?iOS:“单向”导航控制器的最佳实践?
【发布时间】:2012-12-17 00:04:07
【问题描述】:

我正在开发一个应用程序,该应用程序本质上是一系列不同的测试(为简单起见,请考虑 SAT 测试或 Mensa 测试)。每个测试都在不同的 View+View Controller 中实现。

最初我想使用 Storyboards 和 UINavigationControllers 来管理测试的顺序和它们之间的转换,但现在我质疑这种方法的有效性。 UINavigationController 是一个堆栈,而我的导航是单向的(一旦你完成了测试,你就不能回去了)。有没有更好的方法来实现该应用程序?我还能以某种方式利用故事板吗?

【问题讨论】:

  • 即使您选择不使用 NavigationController,并且使用故事板,您也需要使用 segues 推送 ViewController。手动执行此操作与使用禁用后退按钮的导航控制器没有什么不同。我没有看到在这里避免使用 NavigationController 的优势。
  • @jhilgert00 为什么他“需要使用 segues 推送 ViewControllers”?使用遏制,这是没有必要的。至于优势,我认为这是因为如果你有很多场景,如果你不需要它们,将它们推入堆栈没有任何好处。只是占用内存。
  • 话虽如此(并演示了如何做),我个人并不倾向于为每个问题设置不同的场景。我将有一个场景,以这样一种方式存储我的问题,即我可以使用单个场景来呈现所有问题,或者为每种“类型”问题提供一个场景。 HTML 将是一种格式。另一种方法是拥有一个包含问题的数据库或 plist,可能包含“标题”、“问题”、“图像”和答案等字段。在做这样的应用程序时,问题应该在应用程序的模型中,而不是在代码/故事板中。
  • @Rob,非常感谢您的出色回答(我将进一步研究它,但看起来我会接受它)。根据您的评论,测试不是简单的问题,它们主要是基于活动或谜题,所以 HTML 并不是一个真正的选择(更好,我想一个可以在 HTML5 中实现一些,如果不是全部的话,但是为什么?)
  • @Rob:“正如 Apple 建议的那样,只有在标准控制器都无法完成这项工作时,才应该使用自定义容器。”这正是我想首先使用UINavigationController 的原因。

标签: ios memory-management uinavigationcontroller uistoryboard


【解决方案1】:

然后只需加载下一个视图控制器并将当前视图(在某些顶级视图或应用程序窗口中)替换为新视图。如果需要,请添加动画。有什么问题?

【讨论】:

  • 故事板非常方便地布置测试并在必要时重新排列顺序。这是主要原因。
【解决方案2】:

您还可以使用视图动画来避免推送视图控制器。您可以像推送 VC 一样提供视图动画

【讨论】:

    【解决方案3】:

    我会使用自定义容器视图控制器。因此,在您的主要场景中,添加一个“容器视图”。如果您的目标是 iOS6,那么在编辑情节提要时会有一个特殊的“容器视图”对象,您现在可以将其拖到自定义容器视图控制器的场景中:

    如果是 iOS 5,那么 (a) 您必须手动创建第一个子场景; (b) 给它一个唯一的故事板 ID(在我的示例中,InitialChild,并且 (c) 您手动实例化第一个子控制器并以编程方式将其添加为子控制器。因此,假设您有一个名为 containerViewUIView在您的自定义容器视图控制器的场景中,您可以使用如下方法:

    - (void)addInitialChild
    {
        UIViewController *child = [self.storyboard instantiateViewControllerWithIdentifier:@"InitialChild"];
    
        [self addChildViewController:child];
        child.view.frame = self.containerView.bounds;
        [self.containerView addSubview:child.view];
        [child didMoveToParentViewController:self];
    }
    

    当你想过渡到下一个场景时,继承你自己的UIStoryboardSegue

    在 ReplaceSegue.h 中:

    @interface ReplaceSegue : UIStoryboardSegue
    
    @end
    

    在 ReplaceSegue.m 中

    @implementation ReplaceSegue
    
    - (void)perform
    {
        UIViewController *source = self.sourceViewController;
        UIViewController *destination = self.destinationViewController;
        UIViewController *container = source.parentViewController;
    
        [container addChildViewController:destination];
        destination.view.frame = source.view.frame;
        [source willMoveToParentViewController:nil];
    
        [container transitionFromViewController:source
                               toViewController:destination
                                       duration:0.5
                                        options:UIViewAnimationOptionTransitionCrossDissolve
                                     animations:^{
                                     }
                                     completion:^(BOOL finished) {
                                         [source removeFromParentViewController];
                                         [destination didMoveToParentViewController:container];
                                     }];
    }
    @end
    

    然后,当从第一个包含的场景到下一个场景进行转场时,指定一个“自定义”转场,并使用这个“ReplaceSegue”作为类(只需单击转场将其选中,然后查看“属性”检查员”)。

    生成的故事板可能如下所示(注意各个子级之间的“{}”名称):


    参考资料:

    【讨论】:

    • 很好的答案,我想我已经掌握了要点,但我仍然有一个疑问:我不能让 Interface Builder 设置与第一个孩子的 rootViewController 关系。你怎么能这样做?
    • @Wolfy 如果你想将容器添加到你的第一个场景,在编辑故事板时,如果你打开“对象库”(你可以按 control-option-command-3),你'将在该列表中看到一个“容器视图”,您可以将其拖到场景中。
    • 哎呀,你的答案里有这个,我的错!
    • btw,值得注意的是,容器视图所需的 Embed Segue 仅适用于 iOS 6。其他一切都应该适用于 iOS 5。
    • @Wolfy 完全正确。我已经相应地更新了我的答案。感谢您指出这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-09
    • 1970-01-01
    • 1970-01-01
    • 2018-09-24
    • 1970-01-01
    • 2012-10-13
    相关资源
    最近更新 更多