动态heightForRowAtIndexPath:包含许多(数千个)单元格

时间:2012-08-27 16:11:37

标签: objective-c uitableview

heightForRowAtIndexPath:中使用动态值时,我遇到了一些性能问题  (我知道这是这种方法,因为如果我设置静态值,响应性会大幅增加)。我的表包含大约3000个单元格。

我理解为什么在使用动态值时性能会受到影响(主要是因为在显示数据之前,必须对表中的每个单元格执行一次方法中的计算),但我无法弄清楚如何制作它更有效率。

在我遇到的许多类似问题中,建议的解决方案是在NSString中使用sizeWithFont的{​​{1}}方法来加快速度。我目前这样做,但表仍然需要约1.5秒加载(并重新加载,这是经常做的)。这太长了,我需要优化它。

我目前正在使用的代码(至少是它的本质)如下:

heightForRowAtIndexPath:

有人能指出我正确的方向来进一步简化这段代码吗?谢谢!

3 个答案:

答案 0 :(得分:5)

我之前遇到过类似的情况。我的解决方案是在执行[tableView reloadData]之前进行所有计算并将高度存储在名为heightsArray的NSMutableArray中。然后

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
   [heightsArray objectAtIndex:indexpath.row];
}

向上和向下滚动时无需计算。从数组中读取简单内容。由于计算是在前期完成的,因此最初的阻止将更多,但在滚动时的性能提升方面是值得的。您还可以在后台线程上执行计算,从而节省处理时间。只需在方法中执行所有操作即可在后台线程上调用并准备高度数组。

答案 1 :(得分:1)

heightForRowAtIndexPath中最耗时的部分是:

[[[dict allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)] objectAtIndex:indexPath.section];

所以,你可以先添加一个属性sortedKeys,然后像这样使用它:

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *key = [sortedKeys objectAtIndex:indexPath.section];
    CGFloat rightMargin = 50.f;
    // ...
}

答案 2 :(得分:0)

crypticcoder有一个很好的建议。我会建议一个变体,它可能更灵活,支持表更改(插入,删除,重新排序)。

创建一个类,该类是UITableViewCell的子类,并向其添加一个cellHeight属性adn ivar cellHeight_。以这种方式合成它:

@synthesize cellHeight=cellHeight_;

使用此类代码在类中以懒惰的方式计算单元格高度:

-(CGFloat) cellHeight{
    if (cellHeight_ != 0)
        return cellHeight_;
    else {
        NSDictionary *dict = alphabetDict;
        CGFloat rightMargin = 50.f;

        NSString *key = [[[dict allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)] objectAtIndex:indexPath.section];
        NSArray *array = [dict objectForKey:key];
        NSString *cellText = [array objectAtIndex:indexPath.row];

        CGSize constraintSize = CGSizeMake(TABLE_WIDTH - (CELL_MARGIN * 2) - rightMargin, 20000.0f);
        CGSize labelSize = [cellText sizeWithFont:[UIFont systemFontOfSize:17] constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];

        cellHeight_ = labelSize.height + (CELL_MARGIN * 2) + 16.f; 
        return cellHeight_; 
    }
}

和sch一样,我不喜欢那里的那种,但如果它不是真正的性能问题,我就把它留在那里。

如果要更改单元格的内容,请确保将cellHeight_重置为零,以便懒惰地重新计算(当需要再次使用时)。