将 UIViewController 的视图添加到另一个 UIViewController 的视图是不是可取?

Posted

技术标签:

【中文标题】将 UIViewController 的视图添加到另一个 UIViewController 的视图是不是可取?【英文标题】:Is it advisable to add a UIViewController's view to another UIViewController's view?将 UIViewController 的视图添加到另一个 UIViewController 的视图是否可取? 【发布时间】:2012-02-23 08:03:34 【问题描述】:

是否建议将UIViewControllerview 添加到另一个UIViewControllerview

请解释为什么这是一种好的做法或不好的做法。

【问题讨论】:

【参考方案1】:

Apple 以及大多数遵循 Apple 指南的人都会告诉您这是不好的做法,Apple 出于这个原因添加了 ViewController 包含 (childViewControllers)。不幸的是,大多数人盲目地遵循这一点,不会告诉你为什么这是不好的做法。我很高兴你提出这个问题。

事实上,在模型-视图-控制器架构中,无论视图包含什么内容,视图都应该是可重用的,因此视图和控制视图内容的对象不应该相同。这正是 UIViewController 在 ios5 之前所做的事情,Apple 不鼓励您多次使用它们,而这是一件非常合乎逻辑的事情。当然,这很令人困惑,很多人都忽略了指导方针,还是照做了,包括我自己,应用程序运行良好并通过了应用程序商店验证,这导致了更多的混乱。 结果是,在 Apple 屈服并给我们定制容器 ViewControllers 一年多之后,直到今天人们仍然会问这个问题。我已经看到人们经常用复杂的答案来回答这个问题,比如将 UIViewController 重新创建为从 NSObject 继承的类来解决非常简单的问题。只是因为 Apple 不鼓励使用 UIViewControllers,甚至不知道为什么。

由于将 ViewController 的视图添加为子视图通常可以完美地工作,并且许多人仍然支持的 iOS4 中不提供 ViewController 包含,因此太多人不理会使用 ViewController 包含。这是更简洁的解决方案,当您想在 ViewControllers 中使用 ViewControllers 时,应尽可能使用它。如果没有,在大多数情况下,您应该能够简单地将 ViewController 的视图添加为子视图,您只需要知道在哪些情况下即可。

如果您只是将 ViewController 的视图添加到另一个视图中,您可以期待以下内容:

不保证调用视图回调方法。 viewWillAppear、viewDidAppear、viewWillDisappear 和 viewDidDisappear 等方法可能会也可能不会被调用。这在很大程度上取决于操作系统版本,在 iOS4 中它们永远不会被调用,在 iOS5 及更高版本中它们大多会被调用。所以你不能重写这些方法,因为你不能依赖它们,你无法控制它们何时、是否或多少次被调用。 唯一能始终正确调用的视图回调方法是 viewDidLoad。 不会调用旋转回调。根据您的情况,这可能是一件大事或根本不重要。如果视图的 autoresizingmask 足以重新定位和重新缩放它,那么你就可以了。如果没有,您总是可以在调用超级视图的 ViewController 的旋转回调时进行自定义实现。 您必须自己保留对 ViewController 的引用,否则它将立即被释放,而其视图仍将由其父视图保留。

我绝对不会鼓励它,但我也不劝阻它。这是情境性的,如果您不再需要支持 iOS4,那么您基本上可以避免它。但是,如果您牢记上面的列表,那么它也不会造成任何伤害,您的应用程序也可以正常运行。

【讨论】:

+1 表示“不保证调用视图回调方法” 在试图找出未调用回调的原因时,我度过了一段有趣的时光。结果?我的控制器在 UINavigationController 中,它的行为很奇怪。【参考方案2】:

有时可以,有时则不行。如果不显示一些图表并解释视图控制器层次结构和视图层次结构之间的关系,很难给出比这更好的答案。

幸运的是,Apple 已经做到了这一点。观看来自WWDC 2011 的“实现 UIViewController Containment”视频,详细了解何时可以,何时不行。

【讨论】:

【参考方案3】:

这实际上是复杂视图层次结构的常见情况。从 iOS 5 开始,UIViewController 允许您添加子视图控制器。当您添加子控制器时,您也将子视图添加到控制器的视图中。

另一方面,你不应该将视图控制器的视图添加到另一个视图控制器而不将其添加为子视图控制器。

但是,不要滥用它。你应该这样做

您正在为一组控制器实现一个容器(类似于您自己的 UINavigationControllerUISplitViewController) 子控制器是独立的。如果子控制器不断调用其父控制器上的方法,反之亦然,那么最好将功能实现到一个控制器中。

【讨论】:

【参考方案4】:

您可能会侥幸逃脱,但可能有更好的方法。认为两者都会试图操纵视图似乎是合理的。我的答案是否定的。

你想完成什么?

【讨论】:

我没有要求任何特定目的。但是你为什么不建议这个呢? 你错了,这就是子视图控制器的全部意义所在。【参考方案5】:

当然,您可以将 UIViewController 的视图添加到另一个 UiViewController 的视图中,至少作为类变量。但我无法理解这个解决方案的最终目标。 我认为这是一种不好的做法,因为应用程序界面的复杂性正在增加。

【讨论】:

他的意思大概是用addSubview: 添加视图。类变量与此有什么关系?【参考方案6】:

通常在模型-视图-控制器架构中,我们可以重用视图。

但对于 UIViewController,它可能并不总是好主意。这可能会使项目架构变得复杂,因为根据 Apple 文档,视图与视图控制器紧密绑定,因此可能不容易管理。

来自 UIViewController 参考: 视图控制器与它们管理的视图紧密绑定,并参与用于处理事件的响应者链。视图控制器是 UIResponder 类的后代,并被插入到托管根视图与其父视图之间的响应者链中,通常属于不同的视图控制器。如果视图控制器的视图不处理事件,视图控制器可以选择处理事件,也可以将事件传递给父视图。

但是,如果两个不同控制器的 UI 存在细微差别,我认为我们可以重用视图。

【讨论】:

以上是关于将 UIViewController 的视图添加到另一个 UIViewController 的视图是不是可取?的主要内容,如果未能解决你的问题,请参考以下文章

将 UIViews 作为子视图添加到 UIViewController [关闭]

如何将子视图添加到 UIViewController 将 UINavigationBar 推到后面

UIView:将 UIViewController 的视图添加为子视图并将其删除

将 UIViewController 添加到 UIScrollView

将带有分页的 UIScrollView 添加到现有的 UIViewController

将 UIViewController 添加到 UICollectionViewCell