我是否在滥用 UIViewController 子类化? [英] Am I abusing UIViewController Subclassing?

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

问题描述

在试图弄清楚为什么没有在我的应用程序中调用 viewWillAppear 时,我遇到了我对 UIViewController 子类的预期用途可能存在的严重误解.

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.

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

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.

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

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

事实上,我认为这或多或少是 Apple 实现 MVC 的全部想法……一个整体的 VC,下面还有其他 VC,都高兴地调用了他们的委托方法.

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.

如果有很多视图(根据定义需要控制)在一个应用程序中来来去去,并且有很多屏幕,在那篇文章中描述的模型中,每个屏幕都应该有一个主 VC 子类,以及所有子视图而是由自定义控制器(恰好控制视图)控制,它们是简单 NSObject 的子类.

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.

在这种情况下,UIViewControllers 应该只直接指向 Window 还是 UINavigationController、UITabBarController 等?

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

在那种情况下,你能保证调用 UIVC Delegate 方法吗?当视图控制器的视图是另一个 VC 的子视图时,这与手动调用委托方法有何不同?

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?

老实说,这似乎是在浪费时间.ViewDidLoad、viewDidLoad、viewDidUnload、viewWillAppear、viewWillDisappear 的自定义实现更不用说像view"这样的简单属性了.

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"...

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

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?

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

Why replicate all of the perceived functionality of UIViewController?

推荐答案

回答标题问题:是.

所以基本上,要么我一直完全错了,或者我在狂野鹅追逐.

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:

  • 当然,视图是作为 UIView 实例或 UIView 子类的任何对象.
  • 在 MVC 的上下文中,视图"被统称为视图",尽管视图"实际上是一组对象,但我们谈论的这个或那个是视图的责任".
  • 谈到视图控制器时,控制器管理的视图"是控制器视图指向的 UIView 实例它包含的子视图层次结构.
  • 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.

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

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.

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

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.

您似乎将这些方法解释为委托方法,但事实并非如此.委托是一个单独的对象,它允许在不需要子类化的情况下自定义委托者.-viewDidLoad-viewWillAppear 是 UIViewController 覆盖点的两个示例,UIViewController 是一个用于子类化的类.视图控制器对象自己调用这些方法,让子类有机会在控制器生命周期中的某个有趣点采取一些行动.

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.

如果 UIViewController 子类不能指望调用viewWillAppear,为什么不直接调用那个方法手动完成吗?

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

好好看看UIViewController 并且您将看到提供的大部分功能与在屏幕上显示视图(即视图层次结构)有关,或者与将控制器与容器"视图控制器(例如 UINavigationController 和 UITabBarController)集成.对于不管理整个屏幕内容的对象,这些都没有用.

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.

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

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?

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

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.

我想在此处添加一个指向Apple 的 iOS 视图控制器编程指南,它为我上面列出的内容提供了很多支持.这是标题为视图控制器管理视图层次结构"的小节中的相关段落:

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":

视图控制器是直接与单个视图对象相关联但那个对象通常只是根更大的视图层次结构的视图也由视图管理控制器.视图控制器起作用作为中央协调代理视图层次结构,处理交换在其观点与任何相关控制器或数据对象.一个视图控制器通常管理与单个相关的视图屏幕的内容价值,虽然在iPad 应用程序这可能并不总是就是这样.

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 是任何想编写 iOS 应用程序的人都必须阅读的内容.如果您有一段时间(或从未)阅读过,那么值得一读.

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).

更新:从 iOS 5 开始,现在可以定义您自己的容器视图控制器,即管理其他视图控制器并可能同时显示多个视图控制器的视图的视图控制器.您可以在上面标题为 创建自定义容器视图控制器.这些都没有真正改变上面的要点:单个视图控制器仍然应该管理视图的层次结构,并且像 -viewDidLoad 这样的方法仍然引用整个视图图而不是单个子视图.视图控制器管理整个屏幕"内容的建议不再完全准确——就像自 iPad 推出以来 UISplitViewController 同时显示来自两个视图控制器的内容一样,你自己的容器现在可以显示多个子视图控制器的视图.编写容器视图控制器是一个有点高级的话题——在尝试创建自己的视图控制器之前,您应该非常熟悉视图控制器的一般使用以及提供的容器视图控制器的工作方式.

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天全站免登陆