如何在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
相关产品推荐
相关产品推荐

