You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UITableView中可编辑UITextView问题:末尾空行无法触发滚动

解决UITableViewCell中空TextView行无法触发滚动的问题

我之前也碰到过一模一样的场景,这个问题的核心是添加空行时,单元格高度更新和滚动操作的时机不匹配——你调用scrollToCursor的时候,单元格的新高度还没完全生效,导致滚动逻辑基于旧的布局计算,自然不会触发预期的滚动行为。

下面是具体的修复方案,分步骤来解决:

1. 修正TextView的高度计算准确性

默认的UITextView带有内置内边距(textContainerInset和lineFragmentPadding),这会导致空行时intrinsicContentSize的高度计算出现偏差。在awakeFromNib里添加以下代码,确保高度计算精准:

override func awakeFromNib() {
    super.awakeFromNib()
    // 移除默认内边距,避免空行高度计算误差
    textView.textContainerInset = UIEdgeInsets.zero
    textView.textContainer.lineFragmentPadding = 0
    
    textViewHeight = textView.intrinsicContentSize.height
    textView.becomeFirstResponder()
}

2. 让滚动操作在单元格高度更新完成后执行

tableView.beginUpdates()和tableView.endUpdates()的布局更新是异步的,直接在之后调用scrollToCursor会拿到旧的布局信息。我们可以借助CATransaction的完成回调,确保滚动在布局更新彻底完成后触发:

修改selfUpdate方法,并调整textViewDidChangeSelection的逻辑:

func textViewDidChangeSelection(_ textView: UITextView) {
    guard let tableView = tableView else { return }
    selfUpdate(in: tableView)
    // 这里不再直接调用scrollToCursor,交给selfUpdate的完成回调处理
}

func selfUpdate(in tableView: UITableView) {
    let newHeight = textView.intrinsicContentSize.height
    guard textViewHeight != newHeight else { return }
    textViewHeight = newHeight

    UIView.setAnimationsEnabled(false)
    CATransaction.begin()
    // 布局更新完成后再执行滚动逻辑
    CATransaction.setCompletionBlock { [weak self] in
        self?.scrollToCursor()
    }
    tableView.beginUpdates()
    tableView.endUpdates()
    CATransaction.commit()
    UIView.setAnimationsEnabled(true)
}

额外优化:强制TextView重新计算高度(可选)

如果偶尔还是出现空行高度不更新的情况,可以在textViewDidChange方法里(别忘了给textView设置delegate)强制让TextView重新计算内在高度:

func textViewDidChange(_ textView: UITextView) {
    textView.invalidateIntrinsicContentSize()
}

这样修改后,无论是添加空行还是输入内容,UITableView都会准确滚动到光标位置了。

内容的提问来源于stack exchange,提问作者Alexey Chekanov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:19:48