自定义 UITableviewCell 放弃内存问题
Posted
技术标签:
【中文标题】自定义 UITableviewCell 放弃内存问题【英文标题】:Custom UITableviewCell abandon memory issue 【发布时间】:2014-07-10 06:47:58 【问题描述】:目前我正在尝试使用来自仪器的数据优化我的 ios 应用程序。我注意到我的一个 UITableViewCell 存在问题,如果点击上面的单元格,我会插入或删除该单元格。问题是我的单元格似乎没有在 cellForRowAtIndexPath 中被回收,而是创建了一个全新的单元格,并且在此之前创建的单元格被丢弃并留在内存中。这导致了一个主要问题,因为每个单元的成本约为 2mb,因此很容易使用大量内存,并且只需轻按单元打开和关闭即可超过 100mb。如下图所示。
我的自定义 UITableViewCell 包含
UIScrollView
自定义UIView
(图形视图)
自定义UIView
(轴视图)
其他一些信息
使用带有UIScrollView
和其他控件的原型单元格(代码中未显示)
GraphicView 子类 uiview 并使用 drawRect 绘制图形。
我不确定我是否使用了正确的方法,因为用户通常一次只会在屏幕上看到一个单元格。我的问题是我的代码有什么问题,为什么我使用了这么多内存,我该如何解决这个问题?
- (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];
【问题讨论】:
如果(...)这个条件是什么?我认为您没有在问题中发布正确的代码。 您正在重复使用您的单元格。但问题在于您的“graphView”和“axisView”。检查单元格中是否存在这些视图,然后跳过该部分代码。希望它会有所帮助。 【参考方案1】:您正在使可重复使用的单元格出列,但请继续向它们添加 graphViews
和 axisViews
。由于它们从未从单元格中删除,因此它们正在加起来。
如果您 a) 检查单元格上是否已经存在这些视图并重新配置它们,或者 b) 在 PTPriceStatCell
上实现 -prepareForReuse
并在那里清理单元格的子视图,问题应该会消失。
最小的清理示例:
NSArray *oldGraphs = [cell.scrollView.subviews filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id subview, NSDictionary *bindings)
return [subview isKindOfClass:[GraphView class]];
]];
[oldGraphs makeObjectsPerformSelector:@selector(removeFromSuperview)];
【讨论】:
非常感谢,这个解决方案奏效了!我不知道这种方法存在。我很感激,昨晚我一直到凌晨 4 点才试图找到没有结果的解决方案。我现在终于可以发布应用程序并获得一些急需的睡眠。再次感谢您。【参考方案2】:只要让 GraphView 和 AxisView 作为 PTPriceStatCell 的属性。并使用 cell.graphView 或 cell.axisView 访问。您的代码每次都在实例化它们并且永远不会释放它。
【讨论】:
我之前尝试过这个解决方案,但没有解决问题。不过感谢您的回答。以上是关于自定义 UITableviewCell 放弃内存问题的主要内容,如果未能解决你的问题,请参考以下文章
自定义 UITableViewCell 的自动布局约束在运行时失败