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

如何在Swift WebView中打开tel、mailto、whatsapp等类型的外部链接

问题根因

  • 你没有给WKWebView设置navigationDelegate,当前仅赋值了uiDelegate = self,导致didFailProvisionalNavigation代理方法完全不会被调用,自定义 scheme 的处理逻辑自然不会生效
  • 针对whatsapp这类第三方自定义 scheme,需要在项目的Info.plist中添加LSApplicationQueriesSchemes白名单配置,否则canOpenURL会返回false,无法正常跳转

修复步骤

1. 给webView添加navigationDelegate赋值

在loadView方法中添加一行webView.navigationDelegate = self,修改后对应代码段如下:

override func loadView() {
    let webConfiguration = WKWebViewConfiguration()
    webView = WKWebView(frame: .zero, configuration: webConfiguration)
    webView.uiDelegate = self
    // 新增这行赋值navigationDelegate
    webView.navigationDelegate = self
    view = webView
}

2. 配置Info.plist白名单

在Info.plist上右键选择「Open As → Source Code」,添加以下内容配置自定义scheme白名单:

<key>LSApplicationQueriesSchemes</key>
<array>
    <string>fb</string>
    <string>whatsapp</string>
    <string>mailto</string>
    <string>tel</string>
</array>

3. (可选优化)用导航决策方法代替错误捕获逻辑

直接在请求发起前判断scheme类型,比捕获加载失败的逻辑更稳定可靠,替换原有的didFailProvisionalNavigation方法为以下两个方法即可:

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
    guard let url = navigationAction.request.url else {
        decisionHandler(.allow)
        return
    }
    
    let scheme = url.scheme?.lowercased() ?? ""
    // 判断是否是需要外部打开的scheme
    if ["tel", "mailto", "whatsapp", "fb"].contains(scheme) {
        if UIApplication.shared.canOpenURL(url) {
            UIApplication.shared.open(url, options: [:])
            decisionHandler(.cancel)
            return
        }
    }
    decisionHandler(.allow)
}

// 保留原错误处理逻辑兼容异常情况
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
    guard let failingUrlStr = (error as NSError).userInfo["NSErrorFailingURLStringKey"] as? String,
          let failingUrl = URL(string: failingUrlStr) else { return }
    
    let scheme = failingUrl.scheme?.lowercased() ?? ""
    if ["tel", "mailto", "whatsapp", "fb"].contains(scheme), UIApplication.shared.canOpenURL(failingUrl) {
        UIApplication.shared.open(failingUrl, options: [:])
        return
    }
}

内容的提问来源于stack exchange,提问作者Hakan göçmen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 07:36:06