views:

233

answers:

3

I have an app that uses a tableview, along with a UIButton that I add as a subview to each custom cell, like this:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];

    checkButton = [[UIButton buttonWithType:UIButtonTypeCustom] initWithFrame:CGRectMake(2.0, 2.0, 40.0, 40.0)];
    [cell.contentView addSubview:checkButton];

    // lot's of other code

    return cell;
}

I thought all was fine until I started using Instruments to make sure I didn't have any memory leaks, but I've found that adding the UIButton as a subview of the cell like that somehow causes a leak within UIKit.

Specifically, I get a memory leak for each cell row (for each time the button is added as a subview), and the leaked object is "CALayer" with the responsible frame being "-[UIView _createLayerWithFrame:]".

Am I doing something wrong here?

A: 

Have you tested this on a physical device or on the simulator?

The simulator is known to have some memory management variations compared to the actual device code. You should always run memory leak tests on a real device.

Otherwise, your code looks correct to me.

Ben S
A: 

Is checkButton a @property(retain) of your class?

Because in that case you should set the property to null after the usage... but you can't as the cell lifecycle of the cell is not under your control; you'll be better off with a local variable.

Also, you should put a [checkButton release] after the addSubview, as the addSubview code does it's own retain/release

Lorenzo Boccaccia
No, you shouldn't call `[checkButton release]` since it was never alloc'ed, new'ed or copy'ed. However, you have a good point about nulling it if it's a retained property.
Ben S
the button is autoreleased as it was created via a class method.
JustinXXVII
I've missed the autorelease, sorry.
Lorenzo Boccaccia
+4  A: 

The code [UIButton buttonWithType] method already includes an initWithFrame method. You need to just use a CGRectMake, and then set the frame of the button.

rectangle = CGRectMake(2.0f,2.0f,40.0f,40.0f);
checkButton = [UIButton buttonWithType:UIButtonTypeCustom];
checkButton.frame = rectangle;
JustinXXVII
That fixed it! Thanks for the help. (and man, you guys are fast with the responses, heh)
Jawboxer
One note, adding "UIButton *checkButton =" causes my app to crash... but leaving it like I had it ("checkButton =") seems to work fine.
Jawboxer
Sorry, looks like you must have it declared in your header. I will edit my comment if it allows!
JustinXXVII