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

如何让WKWebView完全拦截超链接且正常加载显示内容?

WKWebView 全场景链接拦截问题解析与解决

问题现象

使用loadHTMLString加载本地HTML内容时:

  • 仅拦截.linkActivated类型导航时,WebView正常显示,用户点击链接不会跳转,代码如下:
extension AuthorizationContentView: WKNavigationDelegate {
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        if navigationAction.navigationType == .linkActivated {
            decisionHandler(.cancel)
        } else {
            decisionHandler(.allow)
        }
    }
}
  • 若直接在代理方法中返回decisionHandler(.cancel),WebView无法显示内容,代码如下:
extension AuthorizationContentView: WKNavigationDelegate {
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        decisionHandler(.cancel)
        return
    }
}

补充加载HTML的代码:

func setupWebView(content: String) {
    let supportDarkCSS = "<style>:root { color-scheme: light dark; }</style>"

    contentStackView.removeAllArrangedSubviews()
    webView.loadHTMLString(content + supportDarkCSS, baseURL: nil)
    contentStackView.addArrangedSubview(webView)
}

问题原因

直接返回.cancel会拦截所有导航动作,包括loadHTMLString触发的初始渲染导航——这个导航的navigationType为.other,且请求URL为空,被拦截后WebView无法完成HTML内容的加载与渲染。

另外,.linkActivated仅覆盖用户直接点击带href属性链接的场景,像JS触发的用户交互跳转、表单提交等场景,其navigationType并非.linkActivated,需要更全面的判断逻辑。

解决方案

方案1(iOS 13+ 推荐)

利用isUserInitiated属性判断是否为用户主动触发的导航,同时允许初始加载:

extension AuthorizationContentView: WKNavigationDelegate {
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        // 允许初始加载及非用户主动触发的导航(如页面内部资源加载)
        if navigationAction.request.url == nil || !navigationAction.isUserInitiated {
            decisionHandler(.allow)
        } else {
            // 拦截所有用户主动触发的跳转(含点击链接、JS交互跳转等)
            decisionHandler(.cancel)
            // 如需处理跳转链接,可在此获取URL做后续操作
            if let targetUrl = navigationAction.request.url {
                // 示例:打开系统浏览器
                // UIApplication.shared.open(targetUrl)
            }
        }
    }
}

方案2(兼容iOS 13以下)

通过判断navigationType覆盖常见用户跳转场景,同时放行初始加载:

extension AuthorizationContentView: WKNavigationDelegate {
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        // 放行HTML初始加载请求
        if navigationAction.request.url == nil && navigationAction.navigationType == .other {
            decisionHandler(.allow)
            return
        }
        
        // 拦截所有用户可能触发的跳转类型
        let interceptTypes: [WKNavigationType] = [.linkActivated, .formSubmitted, .backForward, .reload]
        if interceptTypes.contains(navigationAction.navigationType) {
            decisionHandler(.cancel)
            // 处理目标链接逻辑
            if let targetUrl = navigationAction.request.url {
                // ...
            }
        } else {
            decisionHandler(.allow)
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 19:45:43