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

Boo*_*oon 12 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];
}
Run Code Online (Sandbox Code Playgroud)

Cor*_*oyd 24

这一行:

[window addSubview:nav.view];
Run Code Online (Sandbox Code Playgroud)

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

这就是Apple定义委托方法(如viewDidAppear/viewWillAppear)的原因,否则我们就不需要它们,因为我们可以准确地知道这些事件何时发生.

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

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

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

self.navigationController = nav; 
Run Code Online (Sandbox Code Playgroud)

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


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

self.testViewController = [[TestViewController alloc] initWithNibName:@"TestView" bundle: [NSBundle mainBundle]];
Run Code Online (Sandbox Code Playgroud)

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

self.testViewController = [[[TestViewController alloc] initWithNibName:@"TestView" bundle: [NSBundle mainBundle]] autorelease];
Run Code Online (Sandbox Code Playgroud)

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