views:

679

answers:

1

I'm somewhat unclear on the object ownership patterns required for the following instances. When my UIViewController presents a popover controller, an action sheet, or another view controller as modal, am I required to hang onto a retained reference to that child controller until it's been dismissed?

In other words, do the following lines of code effectively "transfer" ownership, or not?

[aPopoverController presentPopoverFromBarButtonItem:someButtonItem permittedArrowDirections:UIPopoverArrowDirectionAny animated:NO];

[anActionSheet showFromBarButtonItem:someButtonItem animated:NO];

[aViewController presentModalViewController:someOtherViewController animated:YES];

Can someone point me to explicit documentation on this subject?

+2  A: 

Presenting a modal view controller retains the UIViewController. This is actually not clear from the docs. However, I tested it using the following code...

NSLog(@"BEFORE %d", [self.setupViewController retainCount]);
[self.navigationController presentModalViewController:self.setupViewController animated:YES];
NSLog(@"AFTER %d", [self.setupViewController retainCount]);

The self.setupViewController is already retained locally, but presenting it output the following:

2010-05-19 10:07:36.687 LocateMe[27716:207] BEFORE 1
2010-05-19 10:07:36.762 LocateMe[27716:207] AFTER 3

So it is probably being retained in the local modalViewController property, as well as in the view hierarchy. Dismissing it will balance these.

So bottom line is, retain it if you want to control it directly, but you don't have to.

EDIT - Just to be clear, the correct pattern is to always retain an object if you set yourself as its delegate. That's because you should be setting the delegate to nil in your dealloc for safety. Practically though, a modal controller is always going to be dismissed before you dealloc, so it's not an issue. You'll notice Apple also breaks this rule in [UIView setAnimationDelegate:], which actually retains the delegate you set.

DougW
I would also add that much of Apple's sample code initializes a UIViewController, presents it modally, and then releases it. Check out the AddMusic example.
DougW
Does the same go for popovers and action sheets?
quixoto
Yes, you can fire UIAlertView and then release it. Or you can retain it if you want to do something to it. Either way is fine, just make sure you balance your retain/releases.
DougW
This is not correct-- if you allocated an autoreleased popover and present it, you'll crash because it gets dealloc'd after being presented. This implies that you must hold onto a reference to the popover until it's dismissed unless you are OK leaking it. This seems totally lame, and inconsistent with the other stuff, but there you are.
quixoto
It is correct, and the alert view does NOT leak. Go read the docs (http://bit.ly/b25V5U). Apple repeatedly demonstrates a pattern of alloc-present-release for both modal windows and alert views.
DougW
@DougW - Is the alloc-present-release pattern used for the UIPopoverController as well?
Florin
@Florin - I don't see an Apple example, but I'm sure it's the same. Since you set a delegate on it, the *correct* pattern should be to retain it, and then set that delegate to nil in your dealloc to be safe. Technically, that's the right way to do things, but since it automatically dies when your view controller does, it's probably not strictly necessary.
DougW