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

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文件")
}

关键逻辑说明

  1. 标签修正:用<a>替代<span>,让浏览器识别可点击链接;
  2. 导航代理拦截:通过WKNavigationDelegate的decidePolicyFor方法,检测到相对路径链接时,从Bundle中获取完整的文件URL并重新加载;
  3. 避免重复加载:在updateUIView中判断当前URL是否和请求URL一致,防止视图刷新时重复加载;
  4. 安全解包:用可选绑定处理文件URL,提升代码稳定性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 08:42:57