38

If I have something like a UILabel linked to a xib file, do I need to release it on dealloc of my view? The reason I ask is because I don't alloc it, which makes me think I don't need to release it either? eg (in the header):

IBOutlet UILabel *lblExample;

in the implementation:

....
[lblExample setText:@"whatever"];
....

-(void)dealloc{
    [lblExample release];//?????????
}
Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
rustyshelf
  • 44,963
  • 37
  • 98
  • 104

8 Answers8

35

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.

Note: The following comments apply only to iOS prior to 3.0. With 3.0 and later, you should instead simply nil out property values in viewDidUnload.

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];
}
mmalc
  • 8,201
  • 3
  • 39
  • 39
  • If we have a retain property, couldn't we simplify this by simply saying self.uiElement = nil; in all places we want to release, since it is a retain property it should actually release it properly as well as set it to nil with no issues, one of the advantages of retain properties. –  Nov 24 '10 at 13:44
  • 1
    You typically would do `self.uiElement = nil;` in `viewDidUnload` not in `setView:`. And it would be clearer to just call `self.anOutlet = nil;` in the dealloc. – Jesse Rusak Jan 15 '11 at 14:38
  • 2
    You shouldn't call self.anOutlet = nil; in the dealloc. It's bad practice to call accessors in dealloc. – tobyc Feb 01 '11 at 01:46
  • 1
    I totally disagree that "It's bad practice to call accessors in dealloc" I do it constantly, this it makes the code a billion times cleaner. Do you have a reference for this? – Wil Shipley Mar 18 '11 at 18:35
  • 1
    @Wil Shipley: Several Apple docs advise against accessors in init and dealloc methods. For example: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html — AFAICT, it's basically that setters can (and under KVO do) have side effects besides just setting the variable, and if you trigger KVO notifications, you might end up telling people to send the object messages after it's deallocated. – Chuck Apr 03 '11 at 06:34
  • This assumes that he's using properties, which aren't necessary if the items aren't going to be accessed from outside the object. – Oscar Feb 29 '12 at 04:39
4

I found what I was looking for in the Apple docs. In short you can set up your objects as properties that you release and retain (or just @property, @synthesize), but you don't have to for things like UILabels:

http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/chapter_3_section_4.html#//apple_ref/doc/uid/10000051i-CH4-SW18

rustyshelf
  • 44,963
  • 37
  • 98
  • 104
3

The

[anOutlet release], anOutlet = nil;

Part is completely superfluous if you've written setView: correctly.

Wil Shipley
  • 9,343
  • 35
  • 59
  • 1
    Actually, this has changed in 3.0 and beyond, I understand. We now have -viewDidUnload and that's where we release accessors. – Wil Shipley Mar 18 '11 at 18:34
1

If you don’t release it on dealloc it will raise the memory footprint.

See more detail here with instrument ObjectAlloc graph

0

If you dont set the IBOutlet as a property but simply as a instance variable, you still must release it. This is because upon initWithNib, memory will be allocated for all IBOutlets. So this is one of the special cases you must release even though you haven't retained or alloc'd any memory in code.

stephen
  • 1,617
  • 3
  • 20
  • 27
0

Related: Understanding reference counting with Cocoa / Objective C

Community
  • 1
  • 1
Sören Kuklau
  • 19,454
  • 7
  • 52
  • 86
  • 1
    @Soeren: I have already read that article, and understand it's contents. My question was in relation to objects instantiated on an IB xib, which it doesn't cover. Eg: I never actually create or allocate the label, the IB magic does all that. So what I need to know is simple:do I need to release it? – rustyshelf Sep 15 '08 at 04:09
0

You do alloc the label, in a sense, by creating it in IB.

What IB does, is look at your IBOutlets and how they are defined. If you have a class variable that IB is to assign a reference to some object, IB will send a retain message to that object for you.

If you are using properties, IB will make use of the property you have to set the value and not explicitly retain the value. Thus you would normally mark IBOutlet properties as retain:

@property (nonatomic, retain) UILabel *lblExample;

Thus in ether case (using properties or not) you should call release in your dealloc.

Kendall Helmstetter Gelner
  • 74,769
  • 26
  • 128
  • 150
  • 3
    This is not correct. If you do not use properties (or implement your own accessor methods), then whether or not you should release depends on what platform you're on and what is your superclass. If you inherit from NSWindowController, for example, you do not release. – mmalc Oct 11 '08 at 09:50
0

Any IBOutlet that is a subview of your Nib's main view does not need to be released, because they will be sent the autorelease message upon object creation. The only IBOutlet's you need to release in your dealloc are top level objects like controllers or other NSObject's. This is all mentioned in the Apple doc linked to above.

Eric Allam
  • 197
  • 3
  • 11
  • 3
    This is actually wrong. Whether or not you should send top-level objects a release message depends on what platform you're using and from what class your File's Owner inherits. For example, if it inherits from NSWindowController, you do not need to release them. – mmalc Oct 10 '08 at 15:43