Benny33
Benny33

Reputation: 505

Custom UITableviewCell abandon memory issue

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

Some other information

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];
         }
     }
}

Instruments analysis

Upvotes: 0

Views: 354

Answers (2)

mvanallen
mvanallen

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

Ryan
Ryan

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

Related Questions