Reputation: 505
At the moment I'm currently trying to optimise my iOS app with data from instruments. I have noticed an issue with one of my UITableViewCell which I insert or remove if the cell above is tapped. The problem is that my cells don't seem to be recycled in cellForRowAtIndexPath but a completely new cell is created and the cells created before that are abandoned and left in memory. This results in a major issue as each one of the cells cost about 2mb making it quite easy use a lot of memory and surpass 100mb simply by tapping the cell on and off. This is illustrated in the image below.
My custom UITableViewCell contains
UIScrollView
UIView
( Graph View)UIView
(Axis View)Some other information
UIScrollView
and other controls (not shown in code)I'm not sure if I'm using the right approach because the user will most commonly have only one of the cells on screen at one time. My questions is what is wrong with my code, why am I using so much memory, how do I fix this?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if([self.prices[indexPath.row] isEqual:@(1)])
{
static NSString *CellIdentifier = @"statCell";
PTPriceStatCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
int width = kOffsetX + dateRangeInDays * kStepX + kOffsetX;
float axisWidth = //Some calculataion;
cell.scrollView.frame = CGRectMake(0,0,cell.frame.size.width - axisWidth, 128);
GraphView *graphView = [[GraphView alloc]initWithFrame:CGRectMake(axisWidth, 0, width , cell.scrollView.frame.size.height)];
graphView.range = dateRangeInDays;
graphView.xValues= xAxis;
graphView.yValues = yAxis;
graphView.earliestDate = earliestDate;
[cell.scrollView addSubview:graphView];
CGPoint bottomOffset = CGPointMake( cell.scrollView.contentSize.width - cell.scrollView.bounds.size.width,0);
[cell.scrollView setContentOffset:bottomOffset animated:NO];
YAxis *axisView = [[YAxis alloc]initWithFrame:CGRectMake(0, cell.scrollView.frame.origin.y, axisWidth, cell.scrollView.frame.size.height)];
axisView.yValues = yAxis;
[cell.contentView addSubview:axisView];
cell.scrollView.contentSize = CGSizeMake(cell.scrollView.graphView.frame.size.width + axisWidth, cell.scrollView.graphView.frame.size.height);
return cell;
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (range < [self.prices count] && [[self.prices objectAtIndex:range] isEqual:@(1)])
{
[self.prices removeObjectAtIndex:range];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
else
{
Price *currentPrice = self.prices[[self getPricePositionFor:(int)indexPath.row]][0];
if (currentPrice.value != nil)
{
[self.prices insertObject:@(1) atIndex:range];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
}
Upvotes: 0
Views: 354
Reputation: 754
You are dequeueing reusable cells, but keep adding graphViews
and axisViews
to them. As they are never removed from the cells, they are adding up.
The issue should disappear if you either a) check whether those views are already present on the cell and just reconfigure them, or b) implement -prepareForReuse
on the PTPriceStatCell
and clean up the cell's subviews there.
Minimal cleanup example:
NSArray *oldGraphs = [cell.scrollView.subviews filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id subview, NSDictionary *bindings) {
return [subview isKindOfClass:[GraphView class]];
}]];
[oldGraphs makeObjectsPerformSelector:@selector(removeFromSuperview)];
Upvotes: 1
Reputation: 4884
Just let the GraphView and the AxisView as PTPriceStatCell's property. And access with cell.graphView or cell.axisView. Your code is instantiating them every time and never release it.
Upvotes: 0