26

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?

erotsppa
  • 14,248
  • 33
  • 123
  • 181

7 Answers7

35

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.

mahboudz
  • 39,196
  • 16
  • 97
  • 124
9

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.

ZaBlanc
  • 4,679
  • 1
  • 35
  • 38
  • Isn't this answer conflicting with the above one? Do you need to or not? So confused. – erotsppa Oct 08 '09 at 15:40
  • No, it's not conflicting: "Obviously, if you also use properties and retain them, you need to release on dealloc". – mahboudz Oct 08 '09 at 19:23
  • As a test, make a new Nav Based App in Xcode. You will see how they release IBOutlets in their dealloc. – mahboudz Oct 08 '09 at 19:25
8

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];
}
iwat
  • 3,591
  • 2
  • 20
  • 24
2

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.

  • 1
    Key phrase is ("unless.. you reatined it somewhere") which will happen if you use do a property (nonatomic,retain). – Fraggle Dec 07 '10 at 21:23
2

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.

Ying
  • 121
  • 1
  • 2
1

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.

Joe D'Andrea
  • 5,141
  • 6
  • 49
  • 67
1

If this is your BlahViewController.h:

//  BlahViewController.h
#import <UIKit/UIKit.h>
@interface BlahViewController
{
    IBOutlet UINavigationBar *navigationBar;
}
@property (nonatomic, retain) IBOutlet UINavigationBar *navigationBar;

@end

Then this would be your dealloc in BlahViewController.m:

- (void)dealloc
{
    [navigationBar release];
    [super dealloc];
}

However, if this is your BlahViewController.h:

//  BlahViewController.h
#import <UIKit/UIKit.h>
@interface BlahViewController
{
    IBOutlet UINavigationBar *navigationBar;
}

@end

Then this would be your dealloc in BlahViewController.m:

- (void)dealloc
{
    [super dealloc];
}

And finally, if this is your BlahViewController.h:

//  BlahViewController.h
#import <UIKit/UIKit.h>

@interface BlahViewController
{
    IBOutlet UINavigationBar *navigationBar;
    IBOutlet MKMapView *map;
}

@property (nonatomic, retain) IBOutlet UINavigationBar *navigationBar;

@end

Then this would be your dealloc in BlahViewController.m:

- (void)dealloc
{
    [navigationBar release];
    [super dealloc];
}

In short, if you declare it as a property, with retain, then you need to release it.

chown
  • 51,908
  • 16
  • 134
  • 170