我有一个UITableView,有几个不同的部分 . 一个部分包含将在用户将文本键入UITextView时调整大小的单元格 . 另一部分包含呈现HTML内容的单元格,计算高度相对较高 .
现在当用户输入UITextView时,为了让表视图更新单元格的高度,我打电话
[self.tableView beginUpdates];
[self.tableView endUpdates];
但是,当我真的只需要更新输入的 single 单元格时,这会导致表重新计算表中 every 单元格的高度 . 不仅如此,而不是使用 tableView:estimatedHeightForRowAtIndexPath:
重新计算估计的高度,它为每个单元格调用 tableView:heightForRowAtIndexPath:
,即使是那些未显示的单元格 .
有没有办法让表格视图更新单个单元格的高度,而不做所有这些不必要的工作?
Update
我_1148476已尝试使用 reloadRowsAtIndexPaths:
,但它看起来不会起作用 . 即使只有一行调用 reloadRowsAtIndexPaths:
仍然会导致每行调用 heightForRowAtIndexPath:
,即使只为您请求的行调用 cellForRowAtIndexPath:
. 实际上,看起来每次插入,删除或重新加载行时,都会为表格单元格中的每一行调用 heightForRowAtIndexPath:
.
我还尝试在 willDisplayCell:forRowAtIndexPath:
中放置代码来计算单元格出现之前的高度 . 为了使其工作,我需要强制表视图在我进行计算后重新请求行的高度 . 不幸的是,从 willDisplayCell:forRowAtIndexPath:
调用 [self.tableView beginUpdates]; [self.tableView endUpdates];
会导致UITableView 's internal code. I guess they don'中的索引超出范围异常,我们希望我们这样做 .
我可以在SDK中发现一个错误,它响应 [self.tableView endUpdates]
它没有为那些仍然试图找到某种解决方法的单元调用 estimatedHeightForRowAtIndexPath:
. 任何帮助表示赞赏 .
8 回答
我有一个类似的问题(任何变化的tableview的跳动卷轴),因为我有
评论整个功能有帮助 .
如上所述,
reloadRowsAtIndexPaths:withRowAnimation:
只会使表视图向其UITableViewDataSource
询问新的单元格视图,但不会要求UITableViewDelegate
获取更新的单元格高度 .不幸的是,只有通过调用才能刷新高度:
即使两个电话之间没有任何变化 .
如果您计算高度的算法太耗时,您应该缓存这些值 . 就像是:
并确保在内容更改时或在初始时将这些高度重置为
-1
.编辑:
此外,如果您想尽可能地延迟高度计算(直到它们滚动到),您应该尝试实现此功能(仅限iOS 7):
@property (nonatomic) CGFloat estimatedRowHeight
此错误已在iOS 7.1中修复 .
在iOS 7.0中,似乎没有任何解决此问题的方法 . 调用
[self.tableView endUpdates]
会导致为表中的每个单元调用heightForRowAtIndexPath:
.但是,在iOS 7.1中,调用
[self.tableView endUpdates]
会导致heightForRowAtIndexPath:
为可见单元格调用,而estimatedHeightForRowAtIndexPath:
将调用非可见单元格 .可变行高会对表视图性能产生非常不利的影响 . 您正在谈论在某些单元格中显示的Web内容 . 如果我们不是在谈论成千上万的行,那么使用UIWebView而不是UITableView来实现您的解决方案可能是值得考虑的 . 我们有类似的情况,并使用自定义生成的HTML标记的UIWebView,它工作得很漂亮 . 您可能知道,当您拥有包含Web内容的动态单元格时,您会遇到令人讨厌的异步问题:
设置完所需的单元格内容后
等到单元格中的Web视图完成呈现Web内容,
然后你必须进入UIWebView并使用JavaScript - 询问HTML文档有多高
然后更新UITableViewCell的高度 .
没有任何乐趣,并且为用户提供了大量的跳跃和抖动 .
如果你必须使用UITableView,绝对是 cache 计算的行高 . 这样在
heightForRowAtIndexPath:
返回它们会很便宜 . 而不是告诉UITableView做什么,只需快速创建数据源 .有办法吗?答案是不 .
您只能使用heightForRowAtIndexPath . 因此,您所能做的就是尽可能降低成本,例如在数据模型中保留单元格高度的NSmutableArray .
使用以下UITableView方法:
您必须指定要重新加载的NSIndex的NSArray . 如果只想重新加载一个单元格,则可以提供仅包含一个NSIndexPath的NSArray .
始终会调用
heightForRowAtIndexPath:
方法,但这是我建议的解决方法 .每当用户输入
UITextView
时,保存_1545010_的indexPath
的局部变量 . 然后,当调用heightForRowAtIndexPath:
时,验证保存的indexPath
的值 . 如果保存的indexPath
不是nil
,则检索应调整大小的 cell 并执行此操作 . 对于其他单元格,请使用缓存值 . 如果保存的indexPath
是nil
,请执行您需要的常规代码行 .以下是我推荐的方法:
使用
UITextView
属性UITextView
来跟踪需要调整大小的行 .然后,在
UITextView
委托方法textViewDidChange:
中,检索indexPath
并存储它 .savedIndexPath
是一个局部变量 .最后,检查
savedIndexPath
的值并执行它所需的内容 .我希望这有帮助!祝好运 .
我最终找到了解决问题的方法 . 我能够预先计算我需要渲染的HTML内容的高度,并包括高度以及数据库中的内容 . 这样,虽然当我更新任何单元格的高度时,我仍然被迫为所有单元格提供高度,但我不需要做任何昂贵的HTML渲染,所以它非常活泼 .
不幸的是,只有在您预先获得所有HTML内容的情况下,此解决方案才有效 .