Reputation: 20115
Inside the didSelectRowAtIndexPath
function of my UITableViewController
, I place a UIActivityIndicatorView
over the selected UITableViewCell
because tapping this cell can potentially issue a slow server request. I printed out the retain count of the UIActivityIndicatorView
and noticed that it was 3, when I expected it to be 2.
// @property (nonatomic, retain) UIActivityIndicatorView *spinner;
foo.spinner = [[UIActivityIndicatorView alloc]
initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge
];
UITableViewCell *cell = [self.tableView cellForRowAtIndex:indexPath];
[cell addSubView:foo.spinner];
NSLog("retain count of spinner = %d", [foo.spinner retainCount]);
The first retain should happen from foo->setSpinner
. The second retain should happen from the tableView
adding the spinner as a child view. Where is the 3rd retain? How would you avoid this memory leak?
Upvotes: 1
Views: 446
Reputation: 45128
You should do:
UIActivityIndicatorView *aSpinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
foo.spinner = aSpinner;
[aSpinner release];
or
foo.spinner = [[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge] autorelease];
Everything else is fine :)
Remember that synthesizing a property like:
@property (nonatomic, retain) UIActivityIndicatorView *spinner;
is basically like:
- (void)setSpinner:(UIActivityIndicatorView *)aSpinner{
[aSpinner retain];
[spinner release];
spinner = aSpinner;
}
So after doing
foo.spinner = [[UIActivityIndicatorView alloc] init...];
retain count will be 2 (alloc/init : 1 and 2 since the property is retain). Furthermore, doing
[someView addSubview:foo.spinner];
will increase the retain count by 1 so there you have the 3 :)
Upvotes: 2
Reputation: 162722
The absolute retain count of an object is pretty much meaningless and is often very misleading.
Think of the retain count as a delta; you increase it, you decrease it.
So, looking at this code:
// @property (nonatomic, retain) UIActivityIndicatorView *spinner;
// next line is +1 for the property, +1 for the alloc
foo.spinner = [[UIActivityIndicatorView alloc]
initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge
];
UITableViewCell *cell = [self.tableView cellForRowAtIndex:indexPath];
// this line may or may not be +1; doesn't matter. the cell is taking responsibility for
// foo.spinner and whether it retains it or copies it or ignores it is irrelevant
// (obviously, it most likely retains it, but you shouldn't care)
[cell addSubView:foo.spinner];
So, at the end of this, you have two retain count increments that you are responsible for. While you could call release twice in dealloc, that'd be against pattern. So, best to balance the +1 from alloc with a release:
[foo.spinner release];
Upvotes: 1
Reputation: 16861
There is no reason for you to care what the retaincount is. All you should concern yourself with is whether your retains and releases are balanced.
Upvotes: 6
Reputation: 4932
Retain count "flow":
1. First retain on alloc
2. Second foo->setSpinner
3. Third addSubview
Upvotes: 1