1

I'm still a little confused on this.

I'm creating an object programmatically in Xcode, let's say a UILabel, which is also going to be a class wide property.

When is the proper time to release the object, in the method in which it is created, or in the dealloc method like normal IBOutlet objects?

Thanks.

thenameisnick
  • 613
  • 2
  • 10
  • 12
  • 2
    When's it's all grown up, and you know that you've taught it the important parts of what you know, and the real world will teach it the rest. Open the door and let your object fly free. – Ben Zotto Jan 29 '11 at 20:23
  • Not exactly helpful, but quite humorous. Thanks. – thenameisnick Jan 29 '11 at 20:41

2 Answers2

3

This depends on whether your property is set to retain the value or not. Usually you want the accessors (generated by @synthesize) to handle the retain/release when the property is set to a new value. You specify such a property like this:

MyController.h

@interface MyController : UIViewController {
 UILabel *myLabel;
}

@property (nonatomic, retain) UILabel *myLabel;

@end

You can then use @synthesize to generate the default getters and setters. The default setter for a 'retain' property will release the current value and retain the new value. However, nothing is done for you in dealloc. Meaning, that when the controller is destroyed, your reference to you label will leak since release will not be called. For this reason, you need call release on all your 'retain' properties in dealloc, like this:

MyController.m

@implementation MyController

@synthesize myLabel;

-(void) dealloc {
 self.myLabel = nil;

 [super dealloc];
}

@end

Notice that in this case, self.myLabel = nil is almost equivalent to calling [myLabel release] since the setter will call release on the existing value and then call retain on the new value. Since the new value is nil, calling [nil retain] has no effect. I prefer to nil instead of releasing since you are also setting the ivar to nil and avoids dangling pointers.

When you create a property like this programmatically as opposed to from Interface Builder, you don't need to mark it with IBOutlet. In the cases where you do create a control using IB, you should nil all of your IBOutlet references in viewDidUnload. This is because your control could be deallocated along with the view if it wasn't retained. Referencing it afterwards will crash the app so it's a good practice to nil them, like this:

- (void)viewDidUnload {
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;

    self.myIBLabel = nil;
}

Another common mistake that happens when using properties is to omit the 'self' part. If you do not use the self.myIBLabel notation, you are bipassing the getter and setter and working with the ivar directly. This will NOT retain/release the object.

Sebastien Martin
  • 1,341
  • 11
  • 25
  • +1 Very will written with lots those fine little "details" thrown in for good measure. Welcome to SO. –  Jan 29 '11 at 20:37
2

You should release it in the dealloc method, although that depends how you're creating your class property.

If you release it in the method in which you create it, and then use it in some other part of your class (which, since you're making the UILabel a class wide property, I assume you are), you will get a bad access when you try to modify it later on. Note that if you're using a retained property you need to take that into account, in which case you might release the label (because you'll have created it and assigned it to your class property, which will retain it again).

Here's a typical example:

- (void) someMethod {
    UILabel *myLabel = [[UILabel alloc] initWithFrame:myFrame];

    self.textLabel = myLabel;
    [myLabel release];
}


- (void) dealloc {
    [textLabel release];
}
lxt
  • 31,146
  • 5
  • 78
  • 83
  • Although, if you never allocated the object (and used a static factory method which returns an autoreleased object) then you should never release it. – James Bedford Jan 29 '11 at 19:08
  • 1
    That's very true! I've only shown one way of doing it. You could also do something like self.textLabel = [[[UILabel alloc] initWithFrame:myFrame] autorelease], which negates all of the stuff I've done above. This is one of those cases where there are several different approaches, it's best to pick one and stick with it. Apple's memory management document is the most comprehensive reference in this case, much better to rely on that where possible. – lxt Jan 29 '11 at 19:11