Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
437 views
in Technique[技术] by (71.8m points)

iphone - Does UIView's addSubview really retain the view?

I ran into a situation that seems to suggest otherwise. In the following code snippet, if I remove the line: self.navigationController = nav, the root controller's view won't show up, suggesting to me that addSubview might not actually retain the view as otherwise suggested. Any idea?

- (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];
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This line:

[window addSubview:nav.view];

does NOT add a view to the screen immediately. It is displayed by the OS in some future run loop on a possibly different thread. The actual implementation we can't be sure of.

This is why Apple defines delegate methods like viewDidAppear/viewWillAppear, otherwise we would not need them as we would know precisely when these events occur.

Moreover, adding a subview as you said, does indeed retains the view. It does NOT however retain the view controller or the navigation controller. Since the navigation controller WILL retain any added view controllers, we do not have to back them with an ivar.

But, your reference to the navigation controller must persist beyond the scope of the method. or depending on your code it could be dealloc-ed or have its reference lost.

So you must keep a reference to the navigation controller with an ivar and set it like so:

self.navigationController = nav; 

So even though nav.view contains a pointer to testViewController.view, the application has no reference the navigation controller and, by extension, the view. The result is a blank screen.


To make this more obvious that it isn't a retain/release problem, you are actually leaking in the following method:

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

You need to autorelease to balance out your retain/releases by:

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

So, that means your view has never, ever been deallocated any time you have ran this code. Which further assures us that your issue is indeed a lost reference.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...