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

WKWebView启动时decidePolicyFor为何被about:blank请求触发?

问题描述

正在完成Hacking With Swift的《EasyBrowser Challenge》第一部分,要求若用户尝试访问未被允许的URL,需显示提示弹窗说明站点被拦截。

在webView(_:decidePolicyFor:decisionHandler:)方法中实现了拦截未授权主机的逻辑(代码如下),但应用启动时该方法会被URL为about:blank的请求触发,出现两次导航请求:第一次是预期的已授权站点(如apple.com),第二次是about:blank并触发拦截弹窗,且未在启动时触发重载操作。

代码片段:

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
    let url = navigationAction.request.url
    
    if let host = url?.host{
        print(host)
        for website in websites {
            if host.contains(website){
                decisionHandler(.allow)
                return
            }
        }
    }
    let alertController = UIAlertController(title: "Access Blocked!", message: "Website you are trying to access is blocked. Please request access.", preferredStyle: .alert)
    alertController.addAction(UIAlertAction(title: "Go back.", style: .cancel))
    present(alertController, animated: true)
    print("not allowed")
    decisionHandler(.cancel)
}
问题原因与解决方案

原因

WKWebView初始化完成后,默认会自动加载about:blank页面作为初始状态,这会触发一次导航请求。而你启动时主动加载了已授权的站点,因此又会触发第二次导航请求。当前代码未对about:blank做特殊处理,它没有主机地址(host为nil),所以会进入拦截分支,弹出弹窗。

解决方案

在拦截逻辑最开始,先判断请求的URL是否为about:blank,如果是则直接允许导航,跳过后续拦截判断:

修改后的代码:

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
    let url = navigationAction.request.url
    
    // 特殊处理about:blank,直接允许
    if url?.absoluteString == "about:blank" {
        decisionHandler(.allow)
        return
    }
    
    if let host = url?.host{
        print(host)
        for website in websites {
            if host.contains(website){
                decisionHandler(.allow)
                return
            }
        }
    }
    let alertController = UIAlertController(title: "Access Blocked!", message: "Website you are trying to access is blocked. Please request access.", preferredStyle: .alert)
    alertController.addAction(UIAlertAction(title: "Go back.", style: .cancel))
    present(alertController, animated: true)
    print("not allowed")
    decisionHandler(.cancel)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 08:12:49