【问题标题】:Multiple view controllers on screen at once?一次在屏幕上显示多个视图控制器?
【发布时间】:2011-01-26 07:14:44
【问题描述】:

我正试图围绕 Cocoa Touch 中的控制器展开思考。主要问题是我希望一次“在屏幕上”有多个控制器——我希望有一个大视图(带有控制器 A),由它们自己的控制器(比如 B)控制的较小视图组成。我希望这样,因为除法使代码更清晰。不好的是,额外的控制器(B 类)不是屏幕上的“一等公民”,例如它们不会收到自转查询和通知。 (并且不能轻易显示模态控制器,它们必须将presentModal… 消息发送给它们的父控制器。)

从 Cocoa 的角度来看,A 和 B 控制器有什么区别?系统是否保留了某种指向“最前端控制器”的指针,它是向其发送通知和诸如此类的东西的特权控制器?为什么其他控制器不接收它们,即使它们的视图在屏幕上?将多个控制器“显示在屏幕上”是否被视为黑客行为?或者它是否受支持而我只是错过了一些观点?谢谢。


关于我要解决的问题的更多信息:我正在编写一个简单的照片浏览器。照片全屏显示,用户可以左右滑动切换照片。 A 控制器负责滚动部分,B 控制器负责每张照片本身。

隔离 B 似乎是个好主意,因为照片是从网络加载的,并且可能会发生很多事情,例如网络可能已关闭等等。在 B 控制器中,代码相当简单,因为 B 仅适用于一张特定的照片。如果我将代码移到 A 控制器,事情就会变得一团糟。

我不喜欢当前解决方案的唯一一点是我必须手动解决 B 不是“一流”控制器的问题。我必须通过 A 手动将一些调用传递给 B,当 B 想要显示模式对话框时,它必须将 presentModal… 发送给 A。这很难看。

【问题讨论】:

    标签: iphone cocoa-touch uiviewcontroller


    【解决方案1】:

    自 iOS 5 以来,现在有了对这种场景的一流支持,称为控制器包含。

    swift controller containment

    objc controller containment.

    【讨论】:

      【解决方案2】:

      它与原始问题没有密切关系,但很重要。 Apple 在 View Controller Programming Guide 中明确指出,视图控制器负责控制一个屏幕的内容:

      “您创建的每个自定义视图控制器对象都负责管理一个屏幕的内容。视图控制器和屏幕之间的一一对应关系是应用程序设计中非常重要的考虑因素。您应该不要使用多个自定义视图控制器来管理同一屏幕的不同部分。同样,您不应使用单个自定义视图控制器对象来管理多个屏幕的内容。

      注意:如果要将单个屏幕划分为多个区域并分别管理每个区域,请使用通用控制器对象(从 NSObject 降级的自定义对象)而不是视图控制器对象来管理屏幕的每个子部分。然后使用单个视图控制器对象来管理通用控制器对象。视图控制器协调整个屏幕交互,但根据需要将消息转发到它管理的通用控制器对象。”

      但是在 iPad Programming Guide 他们也说可能有容器视图控制器:

      “视图控制器负责单个视图。大多数情况下,视图控制器的视图预计会填充应用程序窗口的整个跨度。但在某些情况下,视图控制器可能嵌入到另一个视图中控制器(称为容器视图控制器)并与其他内容一起呈现。导航和标签栏控制器是容器视图控制器的示例。”

      据我目前所知,我不会在视图控制器中使用子视图控制器,而是尝试将 NSObject 子类化并从我的主视图控制器向它们发送消息。

      还检查这个线程: MGSplitViewController discussion

      【讨论】:

      【解决方案3】:

      首先,这很重要,视图控制器不会“在屏幕上”——视图会。您的“顶级”控制器当然可以将您描述的各种消息传递给它的“子视图控制器”。事实上,这就是大多数应用程序的工作方式。考虑一个有标签栏的应用程序,并且视图使用导航控制器。您实际上有几个视图控制器同时“运行”,每个视图控制器同时在屏幕上具有自己的视图——您的“根”视图控制器将是 UITabBarController 的一个实例(或子类),然后它有几个嵌套的 UINavigationControllers,每个这将显示嵌套的视图控制器(如 UITableViewController 的实例或子类)。

      您可能想了解一下responder chains 的工作原理。考虑一个触摸事件。它将为最接近堆栈顶部的视图生成,该视图可以接收事件,它也在水龙头下方。如果该视图无法处理它,它会向上传递视图层次结构的食物链,直到有东西处理它(然后吃掉它)。

      至于您的问题的具体细节,总的来说,我不确定您所描述的策略究竟在复杂性方面对您有什么好处。这取决于您具体实现的方式,但是为每个小子视图拥有单独的视图控制器可能需要更多的簿记代码,而不是只拥有一个了解其所有子视图组件的视图控制器。

      【讨论】:

      • 很好的答案,谢谢。我知道视图出现在屏幕上,而不是控制器上,这就是为什么我一直在引号中写“在屏幕上”,意思是“在屏幕上显示它的视图”。我会在问题中写更多关于情况的内容。
      【解决方案4】:

      这是一个很老的问题,但我想今天有人可能会遇到同样的问题,所以我想分享我的解决方案。 我正在编写这个应用程序,它只有一个屏幕,上面有很多信息、分页、控件等。因为根据 Apple 的 MVC documentation 关于 ViewControllers 的角色,你不应该在视图本身中实现逻辑,或者访问数据模型直接从中,我不得不在拥有几千行代码的大规模 ViewController 之间做出选择,这既难以维护和调试(即使是单元测试),或者找到一种新方法。

      我的解决方案是使用UIContainerView,如下所示:

      这样,您可以在它自己的 ViewController 中实现每个部分的逻辑,而父视图控制器负责视图的约束和大小。

      注意:这个答案只是一个指导,你可以找到一个很好的详细解释它是如何工作的以及如何实现它HERE

      【讨论】:

        【解决方案5】:

        实际上,您可以让它在 iOS 5 之前运行,因为我们大多数人同时针对 4.x 和 5.x。我创建了一个适用于两者的解决方案,并且效果很好,应用商店中很少有应用程序使用它:) 阅读我为此目的创建的my article about this 或只是download and use a simple class

        【讨论】:

        • 在 ios5 之前(即在我们让 Apple 提供遏制之前),Apple 认为这样做是不好的做法。 Apple 工程师亲自告诉我。
        • 我已经使用这个解决方案一年多了,我从来没有遇到过任何问题。问题是我见过的大多数实现都没有正确处理内存和所有重要方法,而我的确实可以正确处理它。尽可能多的我爱苹果视图控制器包含应该随着 iPad 的发布而引入,因为这是多视图控制器最常见的场景。同样,这是在 appstore 中的许多应用程序中批准的解决方案。此解决方案允许重用 iPhone 视图控制器,而不会大惊小怪或令人头疼。
        猜你喜欢
        • 2013-09-02
        • 1970-01-01
        • 1970-01-01
        • 2014-07-28
        • 2018-07-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多