You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Swift中WKWebView无法打开指定URL,跳转至Safari的问题排查

问题分析与修复方案

嘿,我一眼就瞅到问题的根源了!你添加的decidePolicyFor代理方法逻辑完全写反啦,这才导致所有http/https链接都跳去Safari,根本没法在WKWebView里加载。

问题出在哪?

看你当前的代理代码:只要检测到链接是http://https://开头,你就调用decisionHandler(.cancel)取消WebView的加载,然后用UIApplication.shared.open把链接丢给系统浏览器打开——这可不就是强制跳Safari嘛!完全违背了你想要在WebView内打开页面的需求。

修复后的代理代码

把逻辑调转过来:我们要允许所有http/https链接在WKWebView内加载,只有遇到非http/https的自定义URL Scheme(比如app://mailto:这类)时,再考虑用外部方式处理。修改后的代码如下:

public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { 
    guard let url = navigationAction.request.url else { 
        decisionHandler(.allow) 
        return 
    } 
    let urlString = url.description.lowercased()
    
    // 核心调整:允许http/https链接在WebView内加载
    if urlString.starts(with: "http://") || urlString.starts(with: "https://") { 
        decisionHandler(.allow) 
    } else { 
        // 处理自定义URL Scheme(比如唤起其他App、发送邮件等)
        if UIApplication.shared.canOpenURL(url) {
            UIApplication.shared.open(url, options: [:], completionHandler: nil)
            decisionHandler(.cancel) // 取消WebView加载,交给外部处理
        } else {
            decisionHandler(.allow) // 不支持的Scheme就交给WebView处理(大概率会失败,但留个兜底)
        }
    } 
}

进阶优化(可选)

如果你想要更精细的控制——比如只有你指定的域名(比如yyy.com)留在WebView内,其他域名跳Safari,可以再加一层域名校验:

public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { 
    guard let url = navigationAction.request.url else { 
        decisionHandler(.allow) 
        return 
    } 
    let urlString = url.description.lowercased()
    
    if urlString.starts(with: "http://") || urlString.starts(with: "https://") { 
        // 只允许yyy.com相关的链接在WebView内加载
        if urlString.contains("yyy.com") {
            decisionHandler(.allow)
        } else {
            // 其他域名跳Safari
            UIApplication.shared.open(url, options: [:], completionHandler: nil)
            decisionHandler(.cancel)
        }
    } else { 
        // 处理自定义URL Scheme
        if UIApplication.shared.canOpenURL(url) {
            UIApplication.shared.open(url, options: [:], completionHandler: nil)
            decisionHandler(.cancel)
        } else {
            decisionHandler(.allow)
        }
    } 
}

最后检查

别忘了确认你已经给WKWebView设置了navigationDelegate,比如在viewDidLoad里加上这行代码:

override func viewDidLoad() {
    super.viewDidLoad()
    webView.navigationDelegate = self
    loadURLInWebView()
}

要是没设置代理,你的decidePolicyFor方法根本不会被触发哦!

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

火山引擎 最新活动