I have been under the assumption for a while that viewDidUnload
is always called when a controller is deallocated. Is this a correct assumption?
I've just been exploring some odd things, and set a breakpoint in my controller's viewDidUnload
and it's dealloc
. It appears that dealloc
is called, but the viewDidUnload
method is never called. I even added a self.view = nil
to my dealloc
and it still didn't seem to call it.
Does this mean that retained view objects I have been releasing in the viewDidUnload
method also need to be released in my dealloc
method to be sure they really go away?
I know there are many other questions on StackOverflow about viewDidUnload
, but none specifically address this issue about duplication of release statements between the 2 methods.
A more concrete exmaple in a fresh project on the 3.1.2 SDK:
@implementation TestViewController
@synthesize label;
- (IBAction)push {
TestViewController *controller = [[[TestViewController alloc] initWithNibName:@"TestViewController" bundle:nil] autorelease];
[self.navigationController pushViewController:controller animated:YES];
}
- (void)viewDidUnload {
self.label = nil;
NSLog(@"viewDidUnload was called");
}
- (void)dealloc {
[super dealloc];
NSLog(@"label retain count: %i", [label retainCount]);
}
@end
My app delegate creates a simple navigation controller with one of these as it's root controller. When I tap the button linked to push
3 times, and then hit the back button three times, the following output is generated.
ViewDidUnloadTest[2887:207] label retain count: 2
ViewDidUnloadTest[2887:207] label retain count: 2
ViewDidUnloadTest[2887:207] label retain count: 2
Which is 2 higher that I would think it would be. Retained once by the view and once by the controller. But after the dealloc
I would have expected the view to be gone releasing my label, and the controller to be gone calling viewDidUnload
and releasing it. Although there may be an autorelease
in there throwing off the count at this point.
But at least it's clear that viewDidUnload
is not getting called at all, which contrary to this answer here: Are viewDidUnload and dealloc always called when tearing down a UIViewController?
Perhaps I should simply call [self viewDidUnload]
in all my dealloc methods on controllers? Worse than can happen is that I set a property to nil twice, right?
Unless you need to break a retain cycle, you should generally only be releasing objects in your dealloc
method. viewDidUnload
is an exception; it is invoked in low memory situations and should be used to release anything that you can.
If you do need to release them anywhere else, then always set the reference to nil after the release
. That'll protect your app from blowing up later (likely in dealloc
).
Note that the documentation quite explicitly calls out that the view property will already be nil when viewDidUnload
is called.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With