究竟是如何将UIViewController视图设置为零使视图失去其超视图的



有时我想将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);

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

结果,首先一切正常:

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并没有像预期的那样消失,但superview也消失了。

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。变成nil的是vcPreviousViewController.view.superview,尽管我明确将vcPreviousView Controller.vew设置为nil。

没有理由使用UIViewController。您可以从NSObject继承您的类,但这并不重要。

使用如此棘手的代理是一种糟糕的做法。你会遇到更多这样的问题。

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

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

无论您需要什么:

2a)创建自定义类,可能是singlton。看来你需要像经理一样的人。

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

正如UIViewController视图属性上的Apple文档所说:

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

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

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

最新更新