我滥用UIViewController子类? [英] Am I abusing UIViewController Subclassing?

查看:127
本文介绍了我滥用UIViewController子类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了弄清楚为什么viewWillAppear没有在我的应用程序中被调用我遇到了一个可能是对UIViewController子类的意图使用的一个严重的误解。



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



我肯定认为将UIViewController子类的视图添加到其他UIViewController子类的视图。



事实上,我认为这或多或少是苹果实施MVC的整个想法。一个整体VC,下面的其他VC,都很高兴地得到他们的委托方法调用。



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



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



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



老实说,这似乎是一个巨大的浪费时间。 ViewDidLoad,viewDidLoad,viewDidUnload,viewWillAppear,viewWillDisappear的自定义实现更不用说像视图这样的属性一样简单了...



已经完全错了,或者我在野雁追逐。如果UIViewController子类不能计数到调用viewWillAppear,为什么不手动调用该方法,并用它完成?



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

解决方案


基本上,我已经
完全错了,或者我在狂野的
鹅追逐。


听起来你完全错了。 view这个术语有几个不同但相关的含义:




  • 视图当然是任何UIView实例的对象

  • 在MVC的上下文中,view被集体使用,我们谈论这个或者是视图的责任,即使视图

  • 在讨论视图控制器时,控制器管理的视图是控制器视图指向的UIView实例



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



你提到的方法(-viewDidLoad,-viewWillAppear等)是告诉视图控制器它的视图层次是刚刚加载,即将显示,等等。它们实际上并不意味着引用一个单独的子视图,并且为一个视图控制器需要为每个子视图提供该信息是不寻常的。如果视图层次结构已加载,则视图控制器知道加载了该层次结构中的所有内容。



您似乎将这些方法解释为委托方法,不。委托是一个单独的对象,允许委托者的自定义,而不需要子类化。 -viewDidLoad -viewWillAppear 是UIViewController的覆盖点的两个示例,用于子类化。视图控制器对象调用这些方法本身,使子类有机会在控制器生命周期的有趣点采取一些行动。


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


请仔细阅读 UIViewController ,您将看到提供的大多数功能都与在屏幕上显示视图(即视图层次结构)有关,或者将控制器与container视图控制器,如UINavigationController和UITabBarController。对于没有管理整个屏幕内容的对象,这些都是没有用的。



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



如果您真的想使用这些方法来管理视图控制器视图层次结构的子视图,请创建一个具有-viewDid [Load | Unload | Appear | Disappear]和-viewWill [显示|消失]方法。你可以创建这个类一次,然后再根据你需要的子类,并且没有一个子控制器类将拥有所有额外的,不需要的控制器管理的东西,随同UIViewController。



编辑:我要在 Apple's View Controller Programming Guide for iOS ,它为我上面提供的内容提供了很多支持。以下是View Controllers Manage a View Hierarchy小节的相关段落:


视图控制器直接
与单视图对象
,但该对象通常只是一个更大的视图层次结构
的根
视图,也由视图
控制器管理。视图控制器
作为
视图层次结构的中心协调代理,处理在它的视图和任何相关的
控制器或数据对象之间交换
。单个
视图控制器通常管理与单个
屏幕的内容相关联的
视图,尽管在
iPad应用中,这可能不总是
。 / p>

必须阅读任何人,即使想着编写iOS应用程式,也必须阅读/ p>



更新:从iOS 5开始,现在可以定义自己的容器视图控制器,即视图控制器,管理其他视图控制器,并可能同时显示多个视图控制器的视图。有关详情,请参阅上面链接的 创建自定义容器视图控制器 。这些都没有改变上面的要点:单个视图控制器应该仍然管理视图的层次结构,而且 -viewDidLoad 的方法仍然引用整个视图图形,而不是个别子视图。视图控制器管理内容的整个屏幕的建议不再完全准确 - 正如 UISplitViewController 自从引入之后同时显示来自两个视图控制器的内容iPad,您自己的容器现在可以显示多个子视图控制器的视图。编写容器视图控制器是一个有点高级的话题 - 你应该非常熟悉视图控制器的使用方式以及提供的容器视图控制器在创建自己的视图控制器之前的工作方式。


In trying to figure out why viewWillAppear wasn't being called in my app I came across what may be a gross misunderstanding I hold about the intended use of UIViewController subclasses.

According to the following post viewWillAppear does not run when using addSubView!!! and the link to this blog post: http://blog.carbonfive.com/2011/03/09/abusing-uiviewcontrollers/ UIViewController subclassing should only happen in very specific situations. Most notably when added directly to the UIWindow, or other Apple created custom controllers like UINavigationControllers.

I'm certainly guilty of adding the views of UIViewController subclasses to the views of other UIViewController subclasses.

In fact, I thought this was more or less the whole idea of Apple's implementation of MVC generally... One overall VC, with other VCs beneath, all happily getting their delegate methods called.

If there are a lot of views (which by definition need controlling) coming and going in an app, and lots of screenfulls, in the model described in that post, each screenfull should have one master VC Subclass, with all the subviews controlled instead by custom controllers (which happen to control views) which are subclasses of simple NSObject.

In this case, UIViewControllers should only be directly to the Window or UINavigationController, UITabBarController etc?

Are you guaranteed to get the UIVC Delegate methods called in that case? How Does this differ from calling the delegate methods manually when a viewcontroller's view is a subview of another VC?

Honestly this seems like a tremendous waste of time. Custom implementations of ViewDidLoad, viewDidLoad, viewDidUnload, viewWillAppear, viewWillDisappear not to mention things as simple as properties like, say, "view"...

So basically, either I have been completely wrong, or I'm on a wild goose chase. If UIViewController subclasses can't be counted on to call viewWillAppear, why not just call that method manually, and be done with it?

Why replicate all of the perceived functionality of UIViewController?

解决方案

Answer to title question: Yes.

So basically, either I have been completely wrong, or I'm on a wild goose chase.

It sounds like you've been completely wrong. The term "view" has a few different but related meanings:

  • A view is, of course, any object that's an instance of UIView or a subclass of UIView.
  • In the context of MVC, "view" is used collectively, and we talk about this or that being "the view's responsibility" even though "the view" is really a group of objects.
  • When talking about a view controller, the "view" that the controller manages is the UIView instance that the controller's view points to and the hierarchy of subviews that it contains.

It sounds like your misunderstanding is on this last point. A view controller should manage a single "screenful" of content. If you're using a single view controller object to manage more than one view hierarchy, or if you're using several view controllers to manage different parts of the same view hierarchy, you're using UIViewController in a way which was never intended and which is likely to lead to problems.

The methods that you mentioned (-viewDidLoad, -viewWillAppear, etc.) are meant to tell the view controller that its view hierarchy was just loaded, is about to be displayed, and so on. They're really not meant to refer to an individual subview, and it would be unusual for a view controller to need to be given that information for individual subviews. If the view hierarchy was loaded, then the view controller knows that everything in that hierarchy was loaded.

You seem to be interpreting these methods as delegate methods, but they're not. A delegate is a separate object that allows for customization of the delegator without the need for subclassing. -viewDidLoad and -viewWillAppear are two examples of override points for UIViewController, a class that's intended for subclassing. The view controller object calls these methods itself to give subclasses a chance to take some action at an interesting point in the controller's life cycle.

If UIViewController subclasses can't be counted on to call viewWillAppear, why not just call that method manually, and be done with it?

Take a good look at UIViewController and you'll see that most of the functionality provided has to do with displaying the view (that is, the view hierarchy) on the screen, or with integrating the controller with "container" view controllers such as UINavigationController and UITabBarController. None of that is useful to objects that aren't managing the entire screenful of content.

It happens sometimes that a group of views will replicated on several screens, and in some of those cases it's helpful to manage those views with an object that's separate from the view controller itself. I can see how you'd be tempted to use UIViewController because of its -viewDidLoad and similar methods, but those are really only a small part of what UIViewController does. What would it mean to call -presentModalViewController: on one of those objects? Or to access its navigationController or parentViewController properties?

If you really want to manage subviews of your view controller's view hierarchy using those methods, create a subclass of NSObject that has -viewDid[Load|Unload|Appear|Disappear] and -viewWill[Appear|Disappear] methods. You can create that class once and then subclass it as often as you need to, and none of your "subcontroller" classes will have all the extra, unneeded controller management stuff that comes along with UIViewController.

Edit: I want to add a pointer here to Apple's View Controller Programming Guide for iOS, which provides a lot of support for what I've laid out above. Here's a relevant passage from the subsection titled "View Controllers Manage a View Hierarchy":

View controllers are directly associated with a single view object but that object is often just the root view of a much larger view hierarchy that is also managed by the view controller. The view controller acts as the central coordinating agent for the view hierarchy, handling exchanges between its views and any relevant controller or data objects. A single view controller typically manages the views associated with a single screen’s worth of content, although in iPad applications this may not always be the case.

View Controller Programming Guide is required reading for anyone even thinking of writing an iOS app. It's worth reviewing if you haven't read it in a while (or ever).

Update: Starting with iOS 5, it's now possible to define your own container view controllers, i.e. view controllers that manage other view controllers and potentially display the views of multiple view controllers at the same time. You can read more about it in the guide linked above in the section entitled Creating Custom Container View Controllers. None of this really changes the essential points above: a single view controller should still manage a hierarchy of views, and methods like -viewDidLoad still refer to the entire view graph rather than to individual subviews. The advice that a view controller manages an "entire screenful" of content is no longer completely accurate -- just as UISplitViewController has displayed content from two view controllers simultaneously ever since the introduction of the iPad, your own containers can now show the views of multiple child view controllers. Writing a container view controller is a somewhat advanced topic -- you should be very familiar with the use of view controllers generally and the way the provided container view controllers work before you take a stab at creating your own.

这篇关于我滥用UIViewController子类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆