我滥用UIViewController子类吗?

ave*_*dev 31 iphone cocoa-touch uiviewcontroller uiview ios

在试图找出为什么viewWillAppear没有在我的应用程序中被调用时,我遇到了一个可能是我对UIViewController子类的预期用途的严重误解.

根据以下帖子viewWillAppear在使用addSubView时不运行!以及此博客文章的链接:http://blog.carbonfive.com/2011/03/09/abusing-uiviewcontrollers/ UIViewController子类化应该只在非常具体的情况下发生.最值得注意的是,当直接添加到UIWindow或其他Apple创建的自定义控制器(如UINavigationControllers)时.

我肯定会将UIViewController子类的视图添加到其他UIViewController子类的视图中.

事实上,我认为这或多或少是苹果公司实施MVC的整体想法......一个整体的风险投资公司,其他风险投资公司都在下面,所有人都乐于获得他们的代表方法.

如果有,而不是通过控制了很多意见(其定义需要控制)来了,在一个应用程序去,很多screenfulls的,在该职位描述的模型中,每个screenfull应该有一个主VC子类,所有的子视图自定义控制器(碰巧控制视图)是简单NSObject的子类.

在这种情况下,UIViewControllers应该只是直接到Window或UINavigationController,UITabBarController等?

您是否可以保证在这种情况下调用UIVC Delegate方法?当viewcontroller的视图是另一个VC的子视图时,这与手动调用委托方法有何不同?

老实说,这似乎是浪费时间.viewDidLoad中,viewDidLoad中,viewDidUnload,viewWillAppear中的自定义实现,viewWillDisappear何况事情就这么简单公司,比如,"意见"的属性...

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

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

Cal*_*leb 38

标题问题的答案:是的.

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

听起来你完全错了.术语"视图"有一些不同但相关的含义:

  • 当然,视图是任何UIView实例或UIView子类的对象.
  • 在MVC的上下文中,"视图"被集体使用,我们谈论这个或那个是"视图的责任",即使"视图"实际上是一组对象.
  • 在谈论视图控制器时,控制器管理的"视图"是控制器视图指向的UIView实例以及它包含的子视图的层次结构.

听起来你的误解就是最后一点.视图控制器应该管理单个"屏蔽"的内容.如果您使用单个视图控制器对象来管理多个视图层次结构,或者如果您使用多个视图控制器来管理同一视图层次结构的不同部分,那么您将以一种从未想过的方式使用UIViewController.这可能会导致问题.

您提到的方法(-viewDidLoad,-viewWillAppear等)旨在告诉视图控制器其视图层次结构刚刚加载,即将显示,依此类推.它们实际上并不意味着引用单个子视图,并且视图控制器需要为各个子视图提供该信息是不常见的.如果加载了视图层次结构,则视图控制器知道该层次结构中的所有内容都已加载.

您似乎将这些方法解释为委托方法,但它们不是.委托是一个单独的对象,允许自定义委托者而无需子类化.-viewDidLoad并且-viewWillAppear是UIViewController的两个覆盖点示例,这是一个用于子类化的类.视图控制器对象本身调用这些方法,以便为子类提供在控制器生命周期中的有趣点采取某些操作的机会.

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

仔细看看UIViewController,你会发现提供的大多数功能都与在屏幕上显示视图(即视图层次结构)有关,或者与控制器和"容器"视图控制器(如UINavigationController)集成.和UITabBarController.这些对于不管理整个屏幕内容的对象都没有用.

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

如果您确实想要使用这些方法管理视图控制器视图层次结构的子视图,请创建具有-viewDid [Load | Unload | Appear | Disappear]和-viewWill [Appear | Disappear]方法的NSObject子类.您可以创建该类一次,然后根据需要对其进行子类化,并且您的"子控制器"类都不会拥有UIViewController附带的所有额外的,不需要的控制器管理内容.

编辑:我想在这里向Apple的View Controller Programming Guide for iOS添加一个指针,它为我上面列出的内容提供了很多支持.以下是标题为"视图控制器管理视图层次结构"的子部分的相关段落:

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

对于想要编写iOS应用程序的人来说,View Controller Programming Guide是必读的.如果你有一段时间(或曾经)没有读过它,那值得一试.

更新:从iOS 5开始,现在可以定义自己的容器视图控制器,即管理其他视图控制器的视图控制器,并可能同时显示多个视图控制器的视图.您可以在上面标题为" 创建自定义容器视图控制器"的部分中链接的指南中阅读更多相关信息.这些都不会真正改变上面的要点:单个视图控制器仍然应该管理视图的层次结构,而类似的方法-viewDidLoad仍然是指整个视图而不是单个子视图.视图控制器管理"全屏"内容的建议不再完全准确 - 就像UISplitViewController自iPad推出以来同时显示来自两个视图控制器的内容一样,您自己的容器现在可以显示多个孩子的视图查看控制器.编写容器视图控制器是一个有点高级的主题 - 在创建自己的视图控制器之前,您应该非常熟悉视图控制器的使用以及提供的容器视图控制器的工作方式.

  • 感谢您提供详尽而清晰的解释.在早期对这一点感到困惑的时候,我从未回过头来检查我对此的假设,并阅读了View Controller Programming指南,并提出了错误的想法.现在想一想,我过去一直困惑的一些问题显然是这种误解的结果,特别是viewDidUnload和viewWillAppear的行为.更不用说了,我只能假设我的应用程序的内存和性能都会提高... (4认同)
  • @amergin在iOS 5中,事情有所改变,你现在可以创建自己的容器视图控制器(参见[实现容器视图控制器](http://goo.gl/KZ7Po)),所以现在在某些情况下你可能有更多一个视图控制器同时处于活动状态,但你绝对不需要每个UIView实例都有一个控制器.除此之外,据我所知,上述内容是正确的.如果你遇到麻烦,你可能想发表自己的问题 - 很难在评论中提供很好的帮助. (3认同)
  • 〜2小时后代码被重构以正确实现上述模式,并且它工作得很漂亮.不会再犯那个错误了! (2认同)