我有一个表视图,类似于Mail中的复合屏幕,其中一个单元格用于文本输入。我希望该单元格通过使用自动布局将单元格的contentView限制到其UITextView子视图来自动调整大小。表视图的rowHeight和estimatedRowHeight设置为UITableViewAutomaticDimension。此外,text视图的scrollEnabled属性设置为false,以便报告其intrinsicContentSize。
但是,当用户输入文本行时,单元格不会更新其高度,即使文本视图本身确实更新了其内部内容大小。据我所知,手动请求的唯一方法是表视图调用beginUpdates()和endUpdates()。然后正确更新单元格的高度,但这也会导致重新布局整个表视图。这是(别人的) 演示问题的示例代码。
如何在不布局整个表视图的情况下反映单元格文本视图中的更改?
发布于 2016-02-10 17:12:12
节流溶液
reloadRowsAtIndexPaths的问题是,UITextField将resignFirstResponder,因为从本质上讲,单元是重新加载的:即销毁。
相反,beginUpdates() & endUpdates()确实维护现有的单元格,但是在包含scrollEnabled UITextView的单元格上调用时会感到不安,如果每个textViewDidChange都被触发。
限制更新频率
此解决方案基于流行的textViewDidChange方法,仅通过推迟更新来减少或停止闪烁。
UITableViewCell**:** 子类
class TableViewTextViewCell : UITableViewCell, UITextViewDelegate {
var refreshCell:(() -> Void)? = nil
var textViewDirtyCount = 0
// MARK: - UITextViewDelegate
func textViewDidChange(_ textView: UITextView) {
textViewDirtyCount += 1
perform(#selector(TableViewTextViewCell.queuedTextVewDidChange),
with: nil,
afterDelay: 0.3) // Wait until typing stopped
}
func textViewDidBeginEditing(_ textView: UITextView) {
textViewDirtyCount = 0 // initialize queuedTextVewDidChange
}
func textViewDidEndEditing(_ textView: UITextView) {
textViewDirtyCount = -1 // prevent any further queuedTextVewDidChange
}
func queuedTextVewDidChange() {
if textViewDirtyCount > 0 {
textViewDirtyCount -= 1
if 0 == textViewDirtyCount, let refreshCell = refreshCell {
refreshCell()
}
}
}
}脱队列&更新闭包:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(
"cell", forIndexPath: indexPath) as! TableViewTextViewCell
cell.refreshCell = {
() -> Void in
tableView.beginUpdates()
tableView.endUpdates()
}
return cell
}注意上次输入字符后的0.3秒延迟;如果上次更改后不足0.3秒,则不会进行任何更新。这大大减少了闪烁。

GitHub上的►找到了这个解决方案,还有关于斯威夫特的其他详细信息。
发布于 2018-01-28 07:29:26
如果在调用beginUpdates之前禁用UIView动画,则该方法可以工作。
//inside of cellForRowAtIndexPath
cell.performCellUpdates = { [unowned self] in
UIView.setAnimationsEnabled(false) //the secret sauce, prevents the jitter
self.tv.beginUpdates()
self.tv.endUpdates()
UIView.setAnimationsEnabled(true) //don't forget to turn animations back on
}
...
//inside of cell subclass
func textViewDidChange(_ textView: UITextView) {
textView.sizeToFit()
performCellUpdates()
}发布于 2016-02-07 21:47:31
不能更改现有UITableViewCell的高度。您要告诉UITableView单元格无效,然后重新加载它。
在重新加载单元格(cellForRowAtIndexPath)时,您可以传递新的更新的单元格。使用tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)触发单个单元格刷新。
reloadRowsAtIndexPaths并没有reloadData()那么激烈。这是一个准时的索引刷新,不需要被tableView.beginUpdates和tableView.endUpdates包围,您可以提供自己选择的动画方法,比如.Fade。
参见reloadRowsAtIndexPaths(_:withRowAnimation:)中的文档。
还可以访问这个堆栈溢出回答,它详细描述了更改单元格高度的情况。

https://stackoverflow.com/questions/35259289
复制相似问题