If you follow what is now considered to be best practice, you should release outlet properties, because you should have retained them in the set accessor:
@interface MyController : MySuperclass {
Control *uiElement;
}
@property (nonatomic, retain) IBOutlet Control *uiElement;
@end
@implementation MyController
@synthesize uiElement;
- (void)dealloc {
[uiElement release];
[super dealloc];
}
@end
The advantage of this approach is that it makes the memory management semantics explicit and clear, and it works consistently across all platforms for all nib files.
One consideration here, though, is when your controller might dispose of its user interface and reload it dynamically on demand (for example, if you have a view controller that loads a view from a nib file, but on request -- say under memory pressure -- releases it, with the expectation that it can be reloaded if the view is needed again). In this situation, you want to make sure that when the main view is disposed of you also relinquish ownership of any other outlets so that they too can be deallocated. For UIViewController, you can deal with this issue by overriding setView:
as follows:
- (void)setView:(UIView *)newView {
if (newView == nil) {
self.uiElement = nil;
}
[super setView:aView];
}
Unfortunately this gives rise to a further issue. Because UIViewController currently implements its dealloc
method using the setView:
accessor method (rather than simply releasing the variable directly), self.anOutlet = nil
will be called in dealloc
as well as in response to a memory warning... This will lead to a crash in dealloc
.
The remedy is to ensure that outlet variables are also set to nil
in dealloc
:
- (void)dealloc {
// release outlets and set variables to nil
[anOutlet release], anOutlet = nil;
[super dealloc];
}