绘制动态UITableView行高的最佳实践

时间:2011-09-27 23:09:57

标签: iphone objective-c ios uitableview

可能是重复但我在SO上找不到具体问题,所以就是这样。

我很想知道动态改变所有行的高度,通常是因为你不知道用于标签的NSString的长度。

我知道您必须使用此委托方法来更改行高:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

问题是这个委托方法是在创建单元格之前调用的(即在cellForRowAtIndexPath之前调用)。

所以,我想到的是在viewWillAppear中创建一个模拟单元格,以及一个将单元格高度添加到映射到表格视图数据源的数组的方法(在我的例子中也是一个数组) )。

viewWillAppear实现了这个获得高度的重要方法:

[NSString sizeWithFont: constrainedToSize: lineBreakMode:]

然后在heightForRowAtIndexPath我可以像这样返回单元格高度:

//cellHeights is an ivar populated in viewWillAppear
return [[cellHeights objectAtIndex:indexPath.row] floatValue];

我想知道是否有更好的方法来动态更改行高?

我意识到这会降低大量行的性能(我相信大于1000)。但就我而言,我的行不会接近那个数字。因此,性能损失可以忽略不计。

提前致谢!

3 个答案:

答案 0 :(得分:8)

好问题!事实上,我在一些应用程序中做了类似的事情。

我可以想到几个替代品,但所有这些都是相同的主题。您也可以在sizeWithFont:内使用heightForRowAtIndexPath:并取消数组。在这种情况下,如果该操作很昂贵,每次重新计算大小时可能会受到性能损失。

您可以对 heightForRowAtIndexPAth:中的cellHeights数组执行“延迟加载”,因此它可能如下所示:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    if ([cellHeights objectAtIndex:indexPath.row] == nil) {
        ... calculate height and store it in the array at the correct index...
    }

    return [[cellHeights objectAtIndex:indexPath.row] floatValue];
}

我在这里想到的优点是你只计算肯定要装载的细胞的高度。如果你在viewWillAppear进行计算,我猜你最终会为每个单元格进行计算,无论它是否显示?

最后,您可以将大小放在数据模型中。例如,如果它是一个字符串数组,则可以创建一个具有两个属性的类:字符串和“representationSize”属性。然后,每次更改字符串的值时,您都可以重新计算字符串的大小。然后,只有一个数组,而不是两个,映射到您的数据源,填充包含字符串的字符串和显示大小的数据类,并在字符串更改时计算值,而不是一次当视图出现时。

无论如何,我很想听听有关这些不同方法的一些评论。

答案 1 :(得分:1)

马修关于将高度放在数据模型中的想法听起来很有趣。这是另一个提出非常类似解决方案的答案:How can I do variable height table cells on the iPhone properly?

答案 2 :(得分:1)

当我滚动tableview(在3gs iPhone上)时,我的UITableView出了问题。我看到了很多滞后。所以我打开时间分析器(非常好的优化工具)和问题是当我调用函数sizeWithFont时。解决此问题的最佳解决方案是在构造函数中调用sizeWithFont。