This has implications on the way I interact with my modal controllers. When I first started out in iOS development, I assumed that UIViewController did not retain the modally presented view. Well, really it was more like I had no reason to assume it did retain them. This left me with fairly awkward attempts at releasing them when I knew they would have finished their dismissal animations:
_myViewController = [[UIViewController alloc] init];
[self. present modalViewController:_myViewController animated:YES];
/*
Some stuff, then in a different method all together,
probably as the result of a delegate callback or something...
*/
[self dismissModalViewControllerAnimiated:YES];
[_myViewController performSelector:@selector(release) withObject:nil afterDelay:0.5f];
Then, I saw the modalViewController property of UIViewController and thought, “Man, I hope it retains that property when a modal view controller is presented.” Sure enough, I logged the retain count on several of these attempts and noticed a general increase immediate after the call to presentModalViewController:animated: (I know, retain counts are not a perfect metric). So, somewhere along the line, I have started using a much nicer pattern where I assume that any controller object I present modally is retained by the presenting controller. This lets me write the standard present code:
UIViewController* myViewController = [[UIViewController alloc] init];
[self presentModalViewController:myViewController animated:YES];
[myViewController release]; // <- Fire and forget!
Now, of course, there is no awkwardness: no need to wait for an animation to finish, or even keep a reference to the presented controller if I don’t need it. I can blindly dismiss it later and not worry about leaking. I like it.
I have logged many a dealloc in my modally presented controllers and they are always called precisely when I want, which leads me to feel confident in my approach: UIViewController‘s presentModalViewController:animated: retains the presented controller as the modalViewController property.
But, and this is the meat of this question, I realized that I can’t confirm this as documented behavior. And if it’s not documented, I should not feel nearly as safe as I do, because Apple makes no promises about the longevity of undocumented behavior. The modalViewController property is publicly readonly, so I can only assume a retain behind the scenes, and the documentation on presentModalViewController:animated: says only:
Sets the modalViewController property to the specified view controller.
“Sets” could be assign or retain. Nothing I read blatantly confirms or denies my position. Since this is an assumption I make often, I would really love it if someone could point out a fact that I have missed somewhere in the bowels of documentation to put my mind at ease about the legitimacy of this practice.
EDIT: In the ebb and flow of day-to-day life in the iOS SDK, I found myself in the header for UIViewController and started reading some of it. I gleaned some useful info that reminded me of this question and I decided to post it, in the event some future user stumbles upon this question and wants as much info as possible to satisfy their paranoia of a very standard practice. The little morsel is simply this, from the @interface ivar block in UIViewController.h:
UIViewController *_childModalViewController;
As opposed to these other declarations:
UIViewController *_parentViewController; // Nonretained
NSHashTable *_childViewControllers; // Nonretained
The comments seem to explicitly state what is not retained. By virtue of a lack of comment on the modal view controller ivar declaration, it would seem it is retained.
The memory management rules of Objective-C define the behaviour, so it doesn’t need to expressly document that it retains the modal view controller. If an object needs to keep a passed object around after the method has finished executing, it will retain the object unless otherwise specified.
So in this case, you should just pass the view controller to
presentModalViewController:animated:and then release it (or use autorelease).This applies everywhere in Objective-C. If an object takes another object as method input, you never have to retain that object on its behalf.
As requested in the comments, if you read Apple’s documentation on memory management, then you’ll find the section on Weak References, which states:
This actually states that this is a convention in itself and that exceptions will be stated in the documentation, however, going to the documentation for
NSTableViewand looking at thesetDataSource:method, we see: