Do you have to release IBOulets in dealloc? I'm not sure on this one because I didn't do the alloc and typically you only release for something you called alloc on. Anyone know?
Your IBOutlets are probably @properties
. If they are, and you have retain
as an attribute, then you do need to release in -dealloc
In other words:
@interface MyViewController : UIViewController {
IBOutlet UITableView *myTable;
}
@property (nonatomic, retain) IBOutlet UITableView *myTable;
@end
You will have to [myTable release];
in your dealloc.
If you make a new Navigation Based App in Xcode, and look in the appdelegate.h:
@interface Untitled1AppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
UINavigationController *navigationController;
}
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
@end
and the dealloc for appdelegate.m:
- (void)dealloc {
[navigationController release];
[window release];
[super dealloc];
}
The key thing to see here are lines like these:
@property (nonatomic, retain) IBOutlet UIWindow *window;
If there is a retain in there, that means that the property is being "owned" by your code and you have to release it.
Of course, there are other ways, such as not declaring the IBOutlets as properties, or declaring them as properties without retaining. I find that in most cases I prefer to have them be retained properties, which I then have to explicitly release. An example of this is when you flip from one view controller to another. As one view controller is dismissed, its views are removed and they are released. Any IBOutlet UILabels on that view would get released too if I don't have them retained. That means that when I flip back to the old view, I have to go through and reset my labels and controls to their last values, when I could have easily kept them saved if I just retain the IBOutlet.
If you just use IBOutlet in your interface, you DO NOT need to release them. Reason being is that unless you explicitly retain them in your code, they are merely being set. They stick around because the view is there. Obviously, if you also use properties and retain them, you need to release on dealloc.
It's not about IBOutlet, it's about your declaration. If you use a new project wizard in Xcode, you probably get some code like this in your header file.
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;
You can see, there's retain keyword in the header file. Following the memory management guideline, you MUST release everything your retain (by calling alloc, copy, retain, etc.). And you have retain in your code then you must release it.
Additionally, the wizard already add some release code for you.
- (void)dealloc {
[tabBarController release];
[window release];
[super dealloc];
}
As you said, you should release everything that you allocated yourself (with alloc
or copy
). It works the other way: you should not release any Cocoa objects you did not allocate yourself (some CoreFoundation functions allocate, and you're responsible for releasing them, but it's not the case here).
If you didn't allocate your IBOutlet, then you don't have to release it, unless of course, for some reason, you retained it somewhere.
To answer the side question by Joe D'Andrea. You can use self.label = nil;
. Because it is calling setLabel, which is auto generated:
- (void)setLabel:(UILabel *)input
{
[label autorelease];
label = [input retain];
}
As you can see the current label
will be released then nil
is assigned to label.
But make sure you don't write it as label = nil
. That will not work.
Because you need to call the auto generated label accessor method.
Here's what I have been doing with regard to IBOutlet
objects (in conjunction with a NIB file):
@interface MyViewController : UIViewController {
UILabel *label;
}
@property (nonatomic, retain) IBOutlet UILabel *label;
@end
@implementation MyViewController
@synthesize label;
- (void)setView:(UIView *)aView {
if (!aView) {
// view is being set to nil
// set outlets to nil to get the benefit of the didReceiveMemoryWarning!
self.label = nil;
}
// Invoke super's implementation last
[super setView:aView];
}
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.label = nil;
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)dealloc {
[label release];
[super dealloc];
}
Side question: Does it make more sense to use self.label = nil
in dealloc, or must release
be explicitly called (for instance, to keep the static analyzer happy)?
I suppose, at that point, we're on our way out anyway, so there's no need to set our IBOutlet objects to nil.
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