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

点击WKWebView内链接触发Completion handler多次调用导致App崩溃如何解决

崩溃原因

你遇到的崩溃是WKNavigationDelegate的强制校验触发的:decidePolicyForNavigationAction的decisionHandler回调必须且仅能调用一次,重复调用就会抛出你遇到的报错并强制崩溃。

你的代码逻辑存在明显漏洞:

  • 当点击的是http/https协议的链接、且链接有可加载的目标frame(navigationAction.targetFrame != nil)时,你先在else分支调用了decisionHandler(.allow),但该分支没有加return终止代码执行,后续代码会继续往下走,再次调用decisionHandler(.cancel),直接触发重复调用的崩溃。
  • 同时你在判断targetFrame的逻辑之后还冗余写了一遍外部浏览器打开链接+取消加载的逻辑,和你前面判断targetFrame的分支逻辑完全冲突。
修复后的完整代码
import UIKit
import WebKit

class Polering: UIViewController, WKNavigationDelegate {
    // 关联StoryBoard中的webView控件
    @IBOutlet weak var webView: WKWebView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 获取index.html文件路径
        guard let htmlPath = Bundle.main.path(forResource: "index", ofType: "html", inDirectory: "www") else {
            return
        }
        // 创建URL用于webView加载
        let url = URL(fileURLWithPath: htmlPath)
        let request = URLRequest(url: url)
        webView.navigationDelegate = self
        webView.load(request)
    }

    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        // 校验是否为链接点击
        if navigationAction.navigationType == .linkActivated {
            // 确保URL存在
            guard let url = navigationAction.request.url else {
                decisionHandler(.cancel)
                return
            }

            // 校验URL的scheme组件
            let components = URLComponents(url: url, resolvingAgainstBaseURL: false)
            if components?.scheme == "http" || components?.scheme == "https" {
                // 新窗口打开的链接跳转外部浏览器
                if navigationAction.targetFrame == nil {
                    UIApplication.shared.open(url)
                    decisionHandler(.cancel)
                } else {
                    // 站内链接直接在当前webView加载
                    decisionHandler(.allow)
                }
                // 处理完http/https链接直接return,避免走后面的默认逻辑
                return
            } else {
                decisionHandler(.allow)
            }
        } else {
            decisionHandler(.allow)
        }
    }
}

内容的提问来源于stack exchange,提问作者Peter Jönsson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 19:54:03