有没有办法更新单个UITableViewCell的高度,而无需重新计算每个单元格的高度?

Chr*_*lli 46 objective-c uitableview ios

我有一个UITableView,有几个不同的部分.一个部分包含将在用户将文本键入UITextView时调整大小的单元格.另一部分包含呈现HTML内容的单元格,计算高度相对较高.

现在当用户输入UITextView时,为了让表视图更新单元格的高度,我打电话

[self.tableView beginUpdates];
[self.tableView endUpdates];
Run Code Online (Sandbox Code Playgroud)

但是,当我真的只需要更新输入的单个单元格时,这会导致表重新计算表中每个单元格的高度.不仅如此,它不是使用重新计算估计的高度,而是要求每个单元格,甚至是那些未被显示的单元格.tableView:estimatedHeightForRowAtIndexPath:tableView:heightForRowAtIndexPath:

有没有办法让表格视图更新单个单元格的高度,而不做所有这些不必要的工作?

更新

我还在寻找解决方案.正如所建议的那样,我已经尝试过使用reloadRowsAtIndexPaths:,但看起来并不会起作用.reloadRowsAtIndexPaths:甚至单行调用仍将导致heightForRowAtIndexPath:每行调用,即使cellForRowAtIndexPath:只调用您请求的行.实际上,heightForRowAtIndexPath:对于表格单元格中的每一行,都会在任何时候插入,删除或重新加载行.

我还尝试将代码willDisplayCell:forRowAtIndexPath:插入到单元格出现之前计算高度.为了使其工作,我需要强制表视图在我进行计算后重新请求行的高度.不幸的是,调用[self.tableView beginUpdates]; [self.tableView endUpdates];from willDisplayCell:forRowAtIndexPath:会导致UITableView内部代码中的索引超出范围异常.我猜他们不指望我们这样做.

我不禁觉得这是SDK中的一个错误,响应[self.tableView endUpdates]它不会调用estimatedHeightForRowAtIndexPath:不可见的单元格,但我仍然试图找到某种解决方法.任何帮助表示赞赏.

Riv*_*era 29

如上所述,reloadRowsAtIndexPaths:withRowAnimation:只会导致表视图询问其UITableViewDataSource新的单元格视图,但不会要求UITableViewDelegate更新的单元格高度.

不幸的是,只有通过调用才能刷新高度:

[tableView beginUpdates];
[tableView endUpdates];
Run Code Online (Sandbox Code Playgroud)

即使两个电话之间没有任何变化.

如果您计算高度的算法太耗时,您应该缓存这些值.就像是:

- (CGFloat)tableView:(UITableView *)tableView
heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    CGFloat height = [self cachedHeightForIndexPath:indexPath];

    // Not cached ?
    if (height < 0)
    {
        height = [self heightForIndexPath:indexPath];
        [self setCachedHeight:height
                 forIndexPath:indexPath];
    }

    return height;
}
Run Code Online (Sandbox Code Playgroud)

并确保将内容重置-1为内容更改时或初始时.

编辑:

此外,如果您想尽可能延迟高度计算(直到它们滚动到),您应该尝试实现此功能(仅限iOS 7+):

@property (nonatomic) CGFloat estimatedRowHeight

提供行高度的非负估计可以提高加载表视图的性能.如果表包含可变高度行,则在加载表时计算所有高度可能会很昂贵.使用估计允许您将几何计算的一些成本从加载时间推迟到滚动时间.

默认值为0,表示没有估计值.


Chr*_*lli 23

此错误已在iOS 7.1中修复.

在iOS 7.0中,似乎没有任何解决此问题的方法.为表中的每个单元调用调用[self.tableView endUpdates]原因heightForRowAtIndexPath:.

但是,在iOS 7.1中,为可见单元调用调用[self.tableView endUpdates]原因heightForRowAtIndexPath:,并estimatedHeightForRowAtIndexPath:为不可见单元调用.


Joh*_*rug 8

可变行高会对表视图性能产生非常不利的影响.您正在谈论在某些单元格中显示的Web内容.如果我们不是在讨论数千行,那么考虑使用UIWebView而不是UITableView来实现解决方案可能是值得考虑的.我们有类似的情况,并使用自定义生成的HTML标记的UIWebView,它工作得很漂亮.您可能知道,当您拥有包含Web内容的动态单元格时,您会遇到令人讨厌的异步问题:

  • 设置完所需的单元格内容后
  • 等到单元格中的Web视图完成呈现Web内容,
  • 然后你必须进入UIWebView并使用JavaScript - 询问HTML文档有多高
  • 然后更新UITableViewCell的高度.

没有任何乐趣,并且为用户提供了大量的跳跃和抖动.

如果你必须使用UITableView,请务必缓存计算的行高.这样返回它们会很便宜heightForRowAtIndexPath:.而不是告诉UITableView做什么,只需快速创建数据源.