iOS Swift中如何在输入时动态获取WKWebView的高度
实现WKWebView用户输入时实时获取高度的方案
核心思路是通过注入JS监听网页内容变化事件,触发时主动将最新高度回传给原生侧,比原生轮询的性能更高、响应更及时。
步骤1:初始化WKWebView时配置消息监听通道
初始化WKWebViewConfiguration,添加脚本消息处理器,用于接收JS端传回的高度数据:
import WebKit class YourViewController: UIViewController, WKScriptMessageHandler { private var webView: WKWebView! override func viewDidLoad() { super.viewDidLoad() let config = WKWebViewConfiguration() let userContentController = WKUserContentController() // 添加消息监听,名称和JS端保持一致 userContentController.add(self, name: "contentHeightChange") config.userContentController = userContentController webView = WKWebView(frame: .zero, configuration: config) webView.navigationDelegate = self view.addSubview(webView) // 此处添加你的webview布局代码 } // 销毁时移除监听,避免内存泄漏 deinit { webView.configuration.userContentController.removeScriptMessageHandler(forName: "contentHeightChange") } }
步骤2:注入JS监听代码,监听内容变化事件
注入JS代码监听用户输入、DOM结构变动等会触发高度变化的事件,每次事件触发时将当前高度回传给原生:
// 在viewDidLoad中添加如下代码,注入JS脚本 let js = """ // 防抖函数,避免频繁回调 function debounce(func, delay) { let timer = null; return function() { clearTimeout(timer); timer = setTimeout(() => func.apply(this, arguments), delay); } } // 上报高度的方法 const reportHeight = debounce(function() { const height = document.body.scrollHeight; window.webkit.messageHandlers.contentHeightChange.postMessage(height); }, 100); // 防抖间隔可自行调整,单位ms // 监听所有可能触发高度变化的事件 document.addEventListener('input', reportHeight); document.addEventListener('DOMContentLoaded', reportHeight); window.addEventListener('resize', reportHeight); // 监听DOM结构变动,适配非输入触发的内容变化 const observer = new MutationObserver(reportHeight); observer.observe(document.body, { childList: true, subtree: true, attributes: true }); """ let userScript = WKUserScript(source: js, injectionTime: .atDocumentStart, forMainFrameOnly: true) config.userContentController.addUserScript(userScript)
步骤3:实现WKScriptMessageHandler协议,接收高度回调
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { guard message.name == "contentHeightChange", let height = message.body as? CGFloat else { return } // 此处拿到实时高度,更新你的布局逻辑 // 注意:如果高度没有变化,不要重复更新约束,避免布局循环 print("最新webview高度:\(height)") }
可选补充:原有加载完成的高度获取逻辑可以保留
你原有didFinish中的高度获取代码可以作为兜底,避免特殊场景下JS事件没有触发导致高度获取异常。
内容的提问来源于stack exchange,提问作者iOS App Developer Swift
相关产品推荐
相关产品推荐

