UIView的addSubview真的保留了视图吗?

时间:2009-06-02 03:09:19

标签: iphone cocoa-touch uikit

我遇到的情况似乎暗示不然。在下面的代码片段中,如果我删除行:self.navigationController = nav,根控制器的视图将不会显示,向我建议addSubview可能实际上不会保留视图,否则建议。有什么想法吗?

- (void)applicationDidFinishLaunching:(UIApplication *)application {   
   self.testViewController = [[TestViewController alloc] initWithNibName:@"TestView" bundle:  [NSBundle mainBundle]];

   UINavigationController *nav = [[UINavigationController alloc]  initWithRootViewController:self.testViewController];

   self.navigationController = nav;  //<-- if this line is removed, test view won't show up

   [window addSubview:nav.view];

   [nav release];
}

3 个答案:

答案 0 :(得分:24)

这一行:

[window addSubview:nav.view];

不会立即向屏幕添加视图。它在一个可能不同的线程上的某个未来的运行循环中由OS显示。实际的实现我们无法确定。

这就是为什么Apple定义了像viewDidAppear / viewWillAppear这样的委托方法,否则我们就不会需要它们,因为我们可以准确地知道这些事件何时发生。

此外,如您所说,添加子视图确实保留了视图。但 NOT 会保留视图控制器或导航控制器。由于导航控制器保留任何添加的视图控制器,因此我们不必使用ivar支持它们。

但是,您对导航控制器的引用必须持久超出方法的范围。或者根据你的代码,它可以被解除分配或丢失它的引用。

因此,您必须使用ivar保留对导航控制器的引用,并将其设置为:

self.navigationController = nav; 

因此,即使nav.view包含指向testViewController.view的指针,该应用程序也没有引用导航控制器,也没有引用视图。结果是一个空白屏幕。


为了使这更加明显,它不是保留/释放问题,您实际上是在使用以下方法泄漏:

self.testViewController = [[TestViewController alloc] initWithNibName:@"TestView" bundle: [NSBundle mainBundle]];

您需要通过以下方式自动发布以平衡您的保留/发布:

self.testViewController = [[[TestViewController alloc] initWithNibName:@"TestView" bundle: [NSBundle mainBundle]] autorelease];

因此,这意味着您的视图从未在您运行此代码时被解除分配。这进一步向我们保证,您的问题确实是一个失去的参考。

答案 1 :(得分:2)

问题可能不是视图没有保留,而是控制器没有被保留。

没有这一行:

self.navigationController = nav

什么都没有保留导航控制器。让视图比控制器更长是很奇怪的。

答案 2 :(得分:0)

这对我来说看起来不是一个保留/释放问题。如果您注释掉self.navigationController = nav;,则视图将不会显示,因为在下一行中,[window addSubview:self.navigationController.view]将不会设置您的self.navigationController属性。它可能是零或者它会崩溃但是如果没有更多的代码就无法确定。