Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do you have to release IBOulets in dealloc?

Tags:

iphone

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?

like image 231
erotsppa Avatar asked Oct 07 '09 03:10

erotsppa


6 Answers

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.

like image 151
mahboudz Avatar answered Nov 06 '22 16:11

mahboudz


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.

like image 35
ZaBlanc Avatar answered Nov 06 '22 16:11

ZaBlanc


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];
}
like image 8
iwat Avatar answered Nov 06 '22 16:11

iwat


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.

like image 2
Thibault Martin-Lagardette Avatar answered Nov 06 '22 16:11

Thibault Martin-Lagardette


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.

like image 2
Ying Avatar answered Nov 06 '22 15:11

Ying


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.

like image 1
Joe D'Andrea Avatar answered Nov 06 '22 17:11

Joe D'Andrea