我滥用UIViewController子类?

在试图找出为什么viewWillAppear没有在我的应用程序中被调用,我遇到了什么可能是我对UIViewController子类的打算使用的严重误解。

根据以下的post, viewWillAppear在使用addSubView的时候不会运行! 和链接到这个博客文章: http : //blog.carbonfive.com/2011/03/09/abusing-uiviewcontrollers/ UIViewController子类只应在非常特定的情况下发生。 最值得注意的是当直接添加到UIWindow,或其他苹果创build自定义控制器像UINavigationControllers。

我当然有罪,UIViewController子类的视图添加到其他UIViewController子类的视图。

事实上,我认为这或多或less是苹果公司实施MVC的总体思路……一个整体的VC,与其他风投公司一起,都乐于让他们的委托方法叫做。

如果在这个post中描述的模型中有很多视图(根据定义需要控制)在应用程序中来回移动,并且有很多screenfull,每个screenfull都应该有一个主VC子类,所有的子视图都由自定义控制器(这恰好控制视图)是简单的NSObject的子类。

在这种情况下,UIViewControllers应该只能直接到窗口或UINavigationController,UITabBarController等?

你保证在这种情况下获得UIVC委托方法吗? 这与当viewcontroller的视图是另一个VC的子视图时手动调用委托方法有什么区别?

老实说,这似乎是一个巨大的浪费时间。 ViewDidLoad,viewDidLoad,viewDidUnload,viewWillAppear,viewWillDisappear的自定义实现不要提到像“视图”等属性一样简单的事情…

所以基本上,要么我完全错了,要么就是疯狂追逐。 如果不能指望UIViewController的子类来调用viewWillAppear,为什么不手动调用该方法,并完成它呢?

为什么要复制UIViewController的所有感知function?

标题问题的回答: 是的。

所以基本上,要么我完全错了,要么就是疯狂追逐。

这听起来像是你完全错了。 “观点”一词有几个不同的但相关的含义:

  • 当然,视图是UIView的实例或UIView的子类的任何对象。
  • 在MVC的背景下,“观点”是集体使用的,即使“观点”实际上是一组对象,我们也谈论这个或那个是“观点的责任”。
  • 在讨论视图控制器时,控制器pipe理的“视图”是控制器视图指向的UIView实例以及它包含的子视图的层次结构。

这听起来像你的误解是在这最后一点。 视图控制器应该pipe理一个“屏幕”的内容。 如果您使用单个视图控制器对象来pipe理多个视图层次结构,或者如果您使用多个视图控制器来pipe理同一视图层次结构的不同部分,那么您使用的UIViewController是从未打算过的这很可能会导致问题。

你提到的方法(-viewDidLoad,-viewWillAppear等)是为了告诉视图控制器,它的视图层次结构刚被加载,即将被显示,等等。 它们实际上不是指单个的子视图,而且视图控制器需要为每个子视图提供这些信息是不常见的。 如果视图层次结构被加载,那么视图控制器知道该层次结构中的所有内容都被加载了。

您似乎将这些方法解释为委托方法,但它们不是。 一个委托是一个独立的对象,允许定制的委托人,而不需要inheritance。 -viewDidLoad-viewWillAppear是UIViewController的一个覆盖点的两个例子,它是用于子类化的类。 视图控制器对象本身调用这些方法,使得子类有机会在控制器的生命周期的一个有趣点进行一些操作。

如果不能指望UIViewController的子类来调用viewWillAppear,为什么不手动调用该方法,并完成它呢?

仔细看看UIViewController ,你会发现提供的大多数function都是在屏幕上显示视图(也就是视图层次结构),或者将控制器与“容器”视图控制器(如UINavigationController和UITabBarController。 这些对于不pipe理整个屏幕内容的对象都没有用处。

有时候会发生一组视图会在几个屏幕上被复制,并且在这些情况下,用与视图控制器本身分离的对象来pipe理这些视图是有帮助的。 我可以看到你将如何使用UIViewController,因为它的-viewDidLoad和类似的方法,但这些只是UIViewController的一小部分。 调用-presentModalViewController:这些对象之一是什么意思? 或者访问其navigationControllerparentViewController属性?

如果你真的想要使用这些方法来pipe理你的视图控制器的视图层次的子视图,创build一个具有-viewDid [Load | Unload | Appear | Disappear]和-viewWill [Appear | Disappear]方法的NSObject的子类。 您可以创build该类一次,然后按需要经常进行子类化,而且任何“子控制器”类都不会拥有UIViewController附带的所有额外的,不必要的控制器pipe理工具。

编辑:我想在这里添加一个指针到苹果公司的视图控制器编程指南的iOS ,这为我已经提出了很多的支持上面。 以下是标题为“视图控制器pipe理视图层次结构”的相关章节:

视图控制器直接与单个视图对象关联,但该对象通常只是由视图控制器pipe理的更大视图层次结构的根视图。 视图控制器充当视图层次结构的中央协调代理,处理其视图和任何相关控制器或数据对象之间的交换。 单个视图控制器通常pipe理与单个屏幕的内容相关的视图,但是在iPad应用中并不总是如此。

视图控制器编程指南是需要阅读任何人甚至想写一个iOS应用程序。 如果你有一段时间没有阅读过(或曾经),值得一读。

更新:从iOS 5开始,现在可以定义自己的容器视图控制器,即pipe理其他视图控制器的视图控制器,并可能同时显示多个视图控制器的视图。 您可以在标题为“ 创build自定义容器视图控制器 ”部分中的上面链接中详细了解它。 这些都没有改变上面的要点:单个视图控制器仍然应该pipe理视图的层次结构,像-viewDidLoad这样的方法仍然引用整个视图而不是单个的子视图。 视图控制器pipe理“整个屏幕”内容的build议不再是完全准确的 – 正如UISplitViewController自iPad引入以来同时显示来自两个视图控制器的内容一样,您自己的容器现在可以显示多个视图子视图控制器。 编写一个容器视图控制器是一个有点高级的话题 – 你应该非常熟悉视图控制器的使用,以及提供的容器视图控制器的工作方式,然后再试图创build自己的视图控制器。