SwiftUI中WKWebView点击本地HTML链接跳转至另一本地HTML的实现
解决SwiftUI中WKWebView本地HTML链接无响应的问题
嘿,我来帮你搞定这个问题!首先得指出一个小错误——你HTML里用了<span href="file://practitionerPolicy.html">,但<span>标签本身并不支持href属性,浏览器根本不会把它识别成可点击的链接,这是第一个要修正的点,得换成标准的<a>标签:
<a href="practitionerPolicy.html">Tap Me!</a>
即使换成<a>标签,WKWebView默认处理本地相对链接还是会有问题,因为它没法直接识别相对路径对应的Bundle文件位置。我们需要给WKWebView添加导航代理,拦截请求并替换成正确的本地文件URL,这样就能在当前WebView里打开目标HTML了。
修改后的WebView实现代码
struct WebView : UIViewRepresentable { let request: URLRequest // 内部协调类,实现WKNavigationDelegate来处理导航逻辑 class Coordinator: NSObject, WKNavigationDelegate { func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { guard let targetUrl = navigationAction.request.url else { decisionHandler(.cancel) return } // 处理无scheme的相对路径链接(本地文件) if targetUrl.scheme == nil { // 从Bundle中查找对应文件的完整URL if let localFileUrl = Bundle.main.url(forResource: targetUrl.path, withExtension: nil) { // 加载正确的本地文件 webView.load(URLRequest(url: localFileUrl)) decisionHandler(.cancel) // 取消原请求,因为我们已经重新发起了正确的加载 return } } // 外部链接或其他情况,允许正常加载 decisionHandler(.allow) } } func makeCoordinator() -> Coordinator { Coordinator() } func makeUIView(context: Context) -> WKWebView { let webView = WKWebView() webView.navigationDelegate = context.coordinator // 设置导航代理 return webView } func updateUIView(_ uiView: WKWebView, context: Context) { // 避免视图更新时重复加载相同请求 if uiView.url != request.url { uiView.load(request) } } }
优化后的SwiftUI视图代码
把原来的强制解包改成可选绑定,避免文件找不到时崩溃:
if let localFilePath = Bundle.main.url(forResource: "EULA for ALP app", withExtension: "html") { VStack{ WebView(request: URLRequest(url: localFilePath)) }.padding([.leading,.trailing],20) } else { Text("无法找到HTML文件") }
关键逻辑说明
- 标签修正:用
<a>替代<span>,让浏览器识别可点击链接; - 导航代理拦截:通过
WKNavigationDelegate的decidePolicyFor方法,检测到相对路径链接时,从Bundle中获取完整的文件URL并重新加载; - 避免重复加载:在
updateUIView中判断当前URL是否和请求URL一致,防止视图刷新时重复加载; - 安全解包:用可选绑定处理文件URL,提升代码稳定性。
内容的提问来源于stack exchange,提问作者Luke Ireton
相关产品推荐
相关产品推荐

