Object leak using "retain"

206 views Asked by At

I have a property defined with retain attribute which I am synthesizing:

@property (nonatomic, retain) UISwitch *mySwitch;

And inside my loadView I am doing this:

self.mySwitch = [[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 40, 20)];

And finally inside my dealloc I am doing this:

self.mySwitch = nil;

Am I leaking this object (mySwitch) as I have used one alloc? Should I autorelease it while assigning it frame?

Please suggest.

4

There are 4 answers

0
fbrereto On BEST ANSWER

The line:

self.mySwitch = [[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 40, 20)];

Actually calls retain twice- once for the alloc and again in the assignment to self.mySwitch (which is a property you've specified should retain any values assigned to it.) The fix I have been told is best is to add a call to autorelease on the line, making it:

self.mySwitch = [[[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 40, 20)] autorelease];
9
Lily Ballard On

Yes, you are leaking. You are creating an owned object with +alloc/-initWithFrame:, then assigning that owned object to a property marked retain. This creates a second owned reference to the object. At this point, you leak your original owned reference, which causes the object itself to leak.

The correct behavior here is to call -autorelease on the object before assigning it to the property.

self.mySwitch = [[[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 40, 20)] autorelease];

On a tangential note, it's not recommended that you access properties inside of -dealloc. The two reasons generally given for this are 1) this will broadcast KVO notifications, which you don't want inside of -dealloc, and 2) if anyone overrides the setter (in this class or a subclass) it may not behave properly. The recommended approach is to simply release the underlying ivar, so you'd see something like the following instead:

[mySwitch release];

Assigning nil to the property is perfectly safe (and recommended) everywhere else.

11
bioffe On

Yes. You are leaking object. Remember one simple rule here:

if you used +alloc there is always must be corresponding -release.

3
Pascalius On

As alternative to autorelease, if you need a tighter memory management this should work for you:

UISwitch *myswitch_tmp= [[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 40, 20)];
self.mySwitch = myswitch_tmp;
[myswitch_tmp release];

and later e.g. in dealloc

[mySwitch release];