如何通过WKWebView的evaluateJavaScript获取meta标签内容?
问题
我尝试获取以下meta标签的内容:
<meta name="WT.z_docTitle" content="Judgment of the Court (Third Chamber) of 19 January 2023.#Administración General del Estado and Others v Asociación para la Defensa de los Intereses Comunes de las Autoescuelas (AUDICA) and Ministerio Fiscal.#Reference for a preliminary ruling – Directive 2006/123/EC – Services in the internal market – Article 2(2)(d) – Substantive scope – Service in the field of transport – Provision of road safety awareness and re-education courses for the recovery of driving licence points – Concession to operate a public service – Article 15 – Requirements – Division of the relevant territory into five lots – Quantitative and territorial limit on access to the activity concerned – Overriding reasons in the public interest – Justification – Road safety – Proportionality – Service of general economic interest.#Case C-292/21."/>
为此我构建了一个WKWebView并尝试调用evaluateJavaScript()方法,代码如下:
import SwiftUI import WebKit struct UIWebView: NSViewRepresentable { typealias NSViewType = WKWebView @Binding var toggle: Bool let url: URL func makeNSView(context: Context) -> WKWebView { let webView = WKWebView(frame: .zero) webView.load(URLRequest(url: url)) return webView } func updateNSView(_ nsView: WKWebView, context: Context) { nsView.load(URLRequest(url: url)) if toggle { toggle.toggle() nsView.evaluateJavaScript("document.querySelector('meta[name=\"WT.z_docTitle\"]').content;") { (result, error) in if error == nil { print(result) } else { if let error = error as? WKError { print(error.localizedDescription) } } } } } }
但运行后仅得到错误提示:
A JavaScript exception occurred
请问如何修改才能获取到指定的字符串内容?
解决方案
你的代码存在两个核心问题,对应修改方法如下:
1. 页面未加载完成就执行JS
在updateNSView中直接调用evaluateJavaScript时,页面可能还处于加载状态,此时document.querySelector无法找到目标meta标签,直接抛出JS异常。
解决方法是通过WKNavigationDelegate监听页面加载完成事件,确保在页面完全加载后再执行JS代码。
2. updateNSView逻辑不合理
每次触发updateNSView都会重新加载页面,导致重复请求;同时toggle的切换逻辑容易引发重复执行或状态混乱。
修改后的完整代码
import SwiftUI import WebKit struct WebView: NSViewRepresentable { @Binding var toggle: Bool let url: URL class Coordinator: NSObject, WKNavigationDelegate { var parent: WebView init(_ parent: WebView) { self.parent = parent } // 页面加载完成后执行JS获取meta内容 func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { guard parent.toggle else { return } // 用可选链避免找不到标签时抛出异常 webView.evaluateJavaScript("document.querySelector('meta[name=\"WT.z_docTitle\"]')?.content;") { result, error in if let content = result as? String { print("获取到的meta内容:\(content)") } else if let error = error { print("错误信息:\(error.localizedDescription)") } // 执行完成后重置toggle,防止重复触发 parent.toggle = false } } } func makeCoordinator() -> Coordinator { Coordinator(self) } func makeNSView(context: Context) -> WKWebView { let webView = WKWebView(frame: .zero) webView.navigationDelegate = context.coordinator webView.load(URLRequest(url: url)) return webView } func updateNSView(_ nsView: WKWebView, context: Context) { // 仅在toggle触发且当前页面URL不匹配时重新加载 if toggle, nsView.url != url { nsView.load(URLRequest(url: url)) } } }
关键修改点说明
- 重命名结构体为
WebView,避免和系统类命名冲突。 - 添加
Coordinator类实现WKNavigationDelegate,在didFinish方法中执行JS,确保页面加载完成。 - JS代码中使用
?.可选链调用,避免找不到meta标签时直接抛出异常。 - 优化
updateNSView逻辑,仅在必要时重新加载页面,减少重复请求。 - 执行完JS后重置
toggle状态,防止重复触发逻辑。
内容的提问来源于stack exchange,提问作者Атанас Начков
相关产品推荐
相关产品推荐

