1

有时我想将 UIViewController 用作真正的“控制器”而不是带有控制器的视图。也就是说,UIViewController 将获得对现有 UIView 的控制。

在嵌套的 UIViewcontroller 中,我的 UIViewController 的视图是其他视图的子视图。

在某些情况下,UIViewController 可能会控制同一个视图,但不会同时控制。

因此,在委托分配期间,我将确保以前的 UIViewController 停止将视图注册为视图。

UITableView * tvDelegated = (UITableView *)self.delegateForTableController.tvDelegated; //Make sure tvDelegated is not deallocated
UIViewController * vcPreviousViewController = [tvDelegated vcImmediateUIViewController];

assert(vcPreviousViewController.view==tvDelegated);

PO(vcPreviousViewController.view);
PO(vcPreviousViewController.view.superview);
PO(tvDelegated);
PO(tvDelegated.superview);
vcPreviousViewController.view=nil;//if the table view used to have a different tableViewController then disassociate that
PO(vcPreviousViewController.view);
PO(vcPreviousViewController.view.superview);
PO(tvDelegated);
PO(tvDelegated.superview);

基本上,我将指向前一个 ViewController 视图的强指针存储在一个名为 tvDelegated 的变量中。这确保视图不会消失。

结果,首先一切正常:

self.BGtableController.view: <UITableView: 0x1dc0d600; frame = (0 0; 320 548); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x1e485850>; layer = <CALayer: 0x1e4e35b0>; contentOffset: {3, 10}>
self.BGtableController.view.superview: <UIView: 0x1e4bd910; frame = (0 0; 320 548); autoresize = W+H; layer = <CALayer: 0x1e4bd970>>
vcPreviousViewController.view: <UITableView: 0x1dc0d600; frame = (0 0; 320 548); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x1e485850>; layer = <CALayer: 0x1e4e35b0>; contentOffset: {3, 10}>
vcPreviousViewController.view.superview: <UIView: 0x1e4bd910; frame = (0 0; 320 548); autoresize = W+H; layer = <CALayer: 0x1e4bd970>>

执行后vcPreviousViewController.view=nil, tvDelegated 没有按预期消失,但超级视图消失了。

vcPreviousViewController.view: <UITableView: 0x1dc0b000; frame = (0 0; 320 568); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x1e4cd330>; layer = <CALayer: 0x1e4cddd0>; contentOffset: {3, 10}>
vcPreviousViewController.view.superview: (null)
tvDelegated: <UITableView: 0x1dc0d600; frame = (0 0; 320 548); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x1e485850>; layer = <CALayer: 0x1e4e35b0>; contentOffset: {3, 10}>
tvDelegated.superview: (null)

这是另一件令人惊奇的事情。vcPreviousViewController.view 不会变为 nil。即使我清楚地将 vcPreviousViewController.view 设置为 nil,但变为 nil 的是 vcPreviousViewController.view.superview。

4

2 回答 2

1

没有理由使用 UIViewController 比。你可以从 NSObject 继承你的类,但这没关系。

使用如此棘手的委托是一种不好的做法。你会收到更多这样的问题。

在同样的情况下我该怎么办:

1)一个屏幕 - 一个视图控制器。不要让你的逻辑更复杂。将所有视图的委托设置为标准 ViewController。

无论您需要:

2a)创建自定义类,可能是单例。看起来你需要像经理这样的东西。

2b)使用通知机制,以防您不需要像经理这样的东西。它可以帮助您避免对委托链接的头痛。

于 2013-07-19T07:54:58.887 回答
0

正如关于 UIViewController 的 view 属性的 Apple 文档所说:

“每个视图控制器对象是其视图的唯一所有者。您不能将同一个视图对象与多个视图控制器对象相关联。此规则的唯一例外是容器视图控制器实现可以将此视图添加为自己的子视图视图层次结构。在添加子视图之前,容器必须先调用其 addChildViewController: 方法来创建两个视图控制器对象之间的父子关系。

如果您访问此属性并且其值当前为 nil,则视图控制器会自动调用 loadView 方法并返回结果视图。”

我想你得到这种行为是因为你没有为 UIViewController 的父/子关系调用正确的方法。因此,您可能会获得视图的缓存版本,该版本已从视图层次结构中拉出,因此没有超级视图。

于 2013-07-19T07:48:50.520 回答