Reputation: 69757
If I call:
-[UITableView dequeueReusableCellWithIdentifier]
and then I choose not to reuse the cell in this method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
is a leak necessarily introduced? My guess is that it would be dealloced
as soon as the autorelease pool drains.
Upvotes: 1
Views: 2426
Reputation: 69757
Yes, this introduces a leak. Try this empirically by subclassing UITableViewCell
:
static int instances = 0;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
NSLog(@"Init! instances=%d", instances++);
}
return self;
}
-(void)dealloc {
NSLog(@"Dealloc! instances=%d", --instances);
}
If you don't use the cell that comes back from dequeueReusableCellWithIdentifier
you will have a leak.
There are two solutions to this problem:
dequeueReusableCellWithIdentifier
as you're supposed to ornil
as the reuseIdentifier
; then no leak will be introduced. This is the best solution unless your table has a lot of rows, and you don't want to deal with the mess of reuse.Upvotes: 4
Reputation: 10336
If you do not return UITableViewCell returned by dequeueReusableCellWithIdentifier
in - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
then it might create a leak or not depending on what you are doing. Cells returned by dequeueReusableCellWithIdentifier
are automatically released when table view is released because table view is holding a reference to every cell returned by this method.
You will have a problem if for example you call dequeueReusableCellWithIdentifier
repeatedly in - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
like this:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CustomCell"];
// calculate height
// ...
}
In above code dequeueReusableCellWithIdentifier
will always return new cell everytime this method is called so memory usage will rise when you scroll the table view. However at some later point in time these cells allocated by dequeueReusableCellWithIdentifier
will be automatically released when table view is realeased.
Upvotes: 1
Reputation: 2411
No, this will not cause a leak, but will not necessarily be memory efficient either. If you wish to have all these cell reuse chores handled automatically for you, consider using a framework such as the excellent Sensible TableView (free).
Upvotes: 0
Reputation: 539775
Yes, dequeueReusableCellWithIdentifier
returns an autoreleased object, and will not cause a memory leak.
But if you choose not to reuse cells (for whatever reason), then there is no need to call dequeueReusableCellWithIdentifier
first.
Update: You can check how many cells are stored in the internal reuse queue with the following code:
NSDictionary *reuseDict = [self.tableView valueForKey:@"reusableTableCells"];
NSArray *reuseArray = [reuseDict objectForKey:CellIdentifier];
NSLog(@"%d", [reuseArray count]);
I tested this with the Master-Detail Xcode application, where I had removed the call to dequeueReusableCellWithIdentifier
. The number of cells in the reuse queue increased to a maximum of 17 in landscape orientation and 23 in portrait. This was exactly the number of visible cells plus one. So the number is indeed limited, even if you never reuse cells.
Upvotes: 2