将一个UIViewController的视图添加到另一个UIViewController的视图中是否可行?

4

UIViewControllerview添加到另一个UIViewControllerview中,这样做是明智的吗?

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

6个回答

6

苹果公司以及遵循苹果指南的大多数人都会告诉你这是一种不好的做法,并且苹果为此添加了ViewController包含(childViewControllers)。不幸的是,大多数人盲目地遵循这个惯例,并且不会告诉您为什么这是不好的做法。我很高兴你问了这个问题。

事实上,在模型-视图-控制器体系结构中,视图应该是可重复使用的,无论它们包含的内容如何,因此控制视图内容的对象和视图本身不应该相同。这正是UIViewController所做的事情,但在iOS5之前,尽管这是一个非常合理的做法,苹果公司仍然不鼓励您使用多个UIViewController。当然,这令人困惑,许多人忽略了这些指南,还是这样做了,包括我自己。应用程序运行良好,并通过应用商店的验证,这导致更多的混乱。 结果是到今天,人们仍然对此提出问题,甚至在苹果公司屈服并给我们自定义容器ViewController一年多之后,问题仍然存在。我经常看到人们对此问题作出复杂的回答,例如基于非常简单的问题重新创建UIViewController类,而不知道为什么苹果公司反对使用UIViewControllers。

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

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

  • 视图回调方法不能保证被调用。例如viewWillAppear、viewDidAppear、viewWillDisappear和viewDidDisappear等方法可能会被调用,也可能不会被调用。这将在很大程度上取决于操作系统版本,在iOS4中它们永远不会被调用,在iOS5及以上版本中它们将大多被调用。因此,您不能重写这些方法,因为您无法依赖它们,也无法控制何时、是否以及会被调用多少次。
  • 唯一始终会正确调用的视图回调方法是viewDidLoad。
  • 旋转回调不会被调用。根据您的情况,这可能很重要,也可能完全不重要。如果视图的自动调整大小掩码足以重新定位和重新缩放,则可以正常使用。如果不能,您始终可以在父视图的ViewController的旋转回调被调用时执行自定义实现。
  • 您必须自己保留对ViewController的引用,否则它将立即被释放,而其视图仍然会被其父视图保留。

我绝对不会鼓励这样做,但也不会反对。这是一种情境性的问题,如果您不再需要支持iOS4,那么大多数情况下都可以避免使用它。但是,如果您记住以上列表,它也不会造成任何损


+1 for "View callback methods are not guaranteed to get called"。当我尝试查找回调未被调用的原因时,我度过了有趣的时光。结果是什么?我的控制器位于UINavigationController中,它的行为很奇怪。 - Sulthan

3
有时是可以的,有时不行。没有展示一些图表并解释视图控制器层次结构和视图层次结构之间关系就很难给出更好的答案。
幸运的是,苹果已经做到了这一点。观看WWDC 2011的“实现UIViewController容器”视频,详细说明什么时候可以,什么时候不可以。

1

这是复杂视图层次结构中常见的情况。自iOS 5以来,UIViewController使您能够添加子视图控制器。当您添加子控制器时,您也将子视图添加到控制器的视图中。

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

然而,不要滥用它。您应该在以下情况下这样做:

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

0

你可能可以这样做,但可能有更好的方法。似乎合理的想法是两者都会尝试操作视图。我的答案是否定的。

你想要实现什么目标?


我并没有特定的目的,但为什么您不建议这样做呢? - RK-
你错了,这就是子视图控制器的全部意义。 - Sulthan

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

1
他的意思是,可能要用 addSubview: 添加视图。那么类变量与此有什么关系? - mattjgalloway

0
通常在Model-View-Controller架构中,我们可以重用视图。
但是对于UIViewController来说,这可能不总是好主意。这可能会使项目架构复杂化,因为根据苹果文档,视图与视图控制器紧密绑定,因此可能不易管理。
从UIViewController参考中: 视图控制器与其管理的视图紧密绑定,并参与处理事件所使用的响应者链。视图控制器是UIResponder类的子孙,插入到被管理的根视图和其父视图之间的响应者链中,后者通常属于不同的视图控制器。如果视图控制器的视图不能处理事件,则视图控制器可以选择处理事件,或将事件传递给父视图。
但是,我认为如果两个不同的控制器之间的用户界面存在微小差异,我们可以重用一个视图。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接