如何在地球中将UIViewController视图设置为nil使视图丢失其超视图?

时间:2013-07-19 07:28:21

标签: objective-c

有时我想使用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没有按预期消失,但超级视图已经消失。

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.superview,即使我清楚地将vcPreviousViewController.view设置为nil。

2 个答案:

答案 0 :(得分:1)

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

使用代表这么棘手是一种不好的做法。你会收到更多这样的问题。

在同一案件中我该怎么做:

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

无论你需要:

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

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

答案 1 :(得分:0)

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

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

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

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