SwiftUI中WebView如何打开Facebook、电话等外部链接?
解决方案
问题根源
WKWebView默认仅处理当前站点的同源导航请求,不会自动处理跨域外部链接、tel(电话)、mailto(邮箱)、社交媒体跳转等特殊scheme的请求,需要手动实现WKNavigationDelegate代理方法拦截导航请求,按需处理不同类型的链接。
完整修改后代码
import SwiftUI import WebKit struct WebView: UIViewRepresentable { let request: URLRequest private var webView: WKWebView? init(request: URLRequest) { let config = WKWebViewConfiguration() config.defaultWebpagePreferences.allowsContentJavaScript = true self.webView = WKWebView(frame: .zero, configuration: config) self.request = request } func makeUIView(context: Context) -> WKWebView { // 绑定导航代理 webView?.navigationDelegate = context.coordinator return webView! } func updateUIView(_ uiView: WKWebView, context: Context) { uiView.load(request) } // 生成代理协调器 func makeCoordinator() -> Coordinator { Coordinator(self) } // 导航代理实现类 class Coordinator: NSObject, WKNavigationDelegate { let parent: WebView init(_ parent: WebView) { self.parent = parent } func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { guard let url = navigationAction.request.url else { decisionHandler(.allow) return } // 处理特殊scheme和外部跳转 let externalSchemes = ["tel", "mailto", "sms", "facetime"] if externalSchemes.contains(url.scheme?.lowercased() ?? "") { // 调用系统原生能力打开电话、邮箱等链接 UIApplication.shared.open(url) decisionHandler(.cancel) return } // 处理http/https外部链接跳转 if url.scheme?.lowercased() == "http" || url.scheme?.lowercased() == "https" { // 判断是否是点击触发的站外跳转,可根据业务调整判断逻辑 if navigationAction.navigationType == .linkActivated { // 点击的外部链接,用系统浏览器打开,也可以选择在当前webView加载 UIApplication.shared.open(url) decisionHandler(.cancel) return } } // 其余站内请求允许加载 decisionHandler(.allow) } } } struct ShowWebpage : View { var urlpage: String var body: some View { // 可选绑定避免无效链接崩溃 if let url = URL(string: urlpage) { WebView(request: URLRequest(url: url)) } else { Text("无效链接") } } }
核心修改说明
- 新增
Coordinator类作为WKNavigationDelegate的实现载体,拦截所有导航请求 - 针对电话、邮箱、短信等系统级scheme,直接调用系统能力打开
- 针对点击触发的http/https外部链接,默认调用系统浏览器打开,如果你需要在当前WebView内打开外部链接,只需删除对应判断逻辑直接返回
.allow即可 - 优化了URL解析的可选绑定,避免无效链接导致App崩溃
内容的提问来源于stack exchange,提问作者SoftGuru
相关产品推荐
相关产品推荐

