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

UITableViewCell中WKWebView内容更新时如何获取正确contentHeight?

解决UITableViewCell中WKWebView内容动态更新时实时获取高度的问题

问题核心

在UITableViewCell内集成WKWebView时,初始高度可通过evaluateJavaScript获取指定div的scrollHeight解决,但网页内点击按钮展开弹窗后,无法实时捕获高度变化——KVO监听scrollView.contentSize仅在滚动后才触发,无法及时更新Cell高度。

最优解决方案:网页主动通知Native高度变化

利用WebKit的消息机制,让网页在DOM高度变化时主动向Native发送最新高度,这是最可靠的方式(网页自身清楚内容变化时机)。

1. 注入DOM监听脚本到WKWebView

初始化WKWebView时,注入MutationObserver脚本监听目标div的高度变化:

// 配置WKWebView内容控制器
let contentController = WKUserContentController()

// 注入监听DOM变化的脚本
let heightObserverScript = """
const targetNode = document.getElementById('svelte');
if (targetNode) {
  // 监听目标div的属性、子节点及后代变化
  const observerConfig = { attributes: true, childList: true, subtree: true };
  const observer = new MutationObserver(() => {
    const latestHeight = targetNode.scrollHeight;
    // 向Native发送最新高度
    window.webkit.messageHandlers.webViewHeightObserver.postMessage(latestHeight);
  });
  observer.observe(targetNode, observerConfig);
}
"""
let userScript = WKUserScript(source: heightObserverScript, 
                              injectionTime: .atDocumentEnd, 
                              forMainFrameOnly: true)
contentController.addUserScript(userScript)

// 添加Native消息处理器
contentController.add(self, name: "webViewHeightObserver")

// 初始化WKWebView
let webConfig = WKWebViewConfiguration()
webConfig.userContentController = contentController
let webView = WKWebView(frame: .zero, configuration: webConfig)

2. Native接收高度更新并刷新Cell

实现WKScriptMessageHandler协议,接收网页发送的高度数据并更新UITableView:

extension RichContentTableViewCell: WKScriptMessageHandler {
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        guard message.name == "webViewHeightObserver", 
              let newHeight = message.body as? CGFloat else { return }
        
        // 更新全局高度缓存
        RichContentTableViewCell.maximumHeight = newHeight
        
        // 刷新当前Cell的高度
        if let tableView = self.superview as? UITableView {
            tableView.beginUpdates()
            tableView.endUpdates()
        }
    }
}

3. 清理资源(避免内存泄漏)

在Cell销毁时移除消息处理器:

deinit {
    webView.configuration.userContentController.removeScriptMessageHandler(forName: "webViewHeightObserver")
}

为什么KVO方案失效?

WKWebView的scrollView.contentSize更新依赖WebKit内部布局流程,DOM变化后不会立即同步到Native层的scrollView属性——只有滚动操作触发强制布局时,contentSize才会更新,因此KVO无法实时捕获高度变化。

备选方案(不推荐,仅作补充)

如果无法修改网页脚本,可尝试在网页按钮点击触发的Native回调中,主动调用evaluateJavaScript获取最新高度:

// 假设通过WKNavigationDelegate捕获按钮点击事件后,主动获取高度
func getLatestWebViewHeight() {
    webView.evaluateJavaScript("document.getElementById('svelte').scrollHeight") { [weak self] result, error in
        guard let self = self, let height = result as? CGFloat else { return }
        RichContentTableViewCell.maximumHeight = height
        self.superview?.beginUpdates()
        self.superview?.endUpdates()
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 11:45:24