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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 11:36:05