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

如何在WKWebView点击链接时弹出Sheet展示链接内容?

解决方案

要实现WKWebView内点击链接弹出独立Sheet展示页面,核心是通过绑定状态在SwiftUI视图层级和UIKit的Coordinator之间传递交互信号,具体修改如下:

1. 定义Sheet用的WebView组件

先封装一个专门用于Sheet的WKWebView包装,方便复用:

struct WebViewSheet: UIViewRepresentable {
    let url: URL
    
    func makeUIView(context: Context) -> WKWebView {
        let webView = WKWebView()
        webView.load(URLRequest(url: url))
        return webView
    }
    
    func updateUIView(_ uiView: WKWebView, context: Context) {}
}

2. 修改HTMLView,添加绑定状态

给HTMLView添加两个绑定变量,用于控制Sheet的显示和要加载的URL,同时启用NavigationDelegate:

struct HTMLView: UIViewRepresentable {
    let html: String
    // 添加绑定状态,用于通知SwiftUI弹出Sheet
    @Binding var showSheet: Bool
    @Binding var sheetURL: URL?
    
    func makeUIView(context: Context) -> WKWebView {
        let webView = WKWebView()
        webView.navigationDelegate = context.coordinator // 启用导航代理
        return webView
    }
    
    func updateUIView(_ uiView: WKWebView, context: Context) {
        uiView.loadHTMLString(html, baseURL: nil)
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    class Coordinator: NSObject, WKNavigationDelegate {
        let parent: HTMLView
        
        init(_ parent: HTMLView) {
            self.parent = parent
        }
        
        func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
            guard let url = navigationAction.request.url, url.scheme != "about" else {
                decisionHandler(.allow)
                return
            }
            
            // 拦截有效链接,触发Sheet弹出
            parent.sheetURL = url
            parent.showSheet = true
            decisionHandler(.cancel) // 取消默认跳转行为
        }
    }
}

3. 修改DetailsView,添加Sheet逻辑

在DetailsView中添加状态变量,管理Sheet的显示,并将状态绑定到HTMLView:

struct DetailsView: View {
    let item: MyItem
    // 本地状态控制Sheet显示
    @State private var showSheet = false
    @State private var sheetURL: URL?
    
    var body: some View {
        HTMLView(html: item.html, showSheet: $showSheet, sheetURL: $sheetURL)
            .padding(30)
            .sheet(isPresented: $showSheet) {
                // Sheet中展示目标页面
                if let url = sheetURL {
                    WebViewSheet(url: url)
                        .edgesIgnoringSafeArea(.all)
                }
            }
    }
}

关键说明

  • 通过@Binding实现UIKit层(Coordinator)和SwiftUI视图层的状态同步,Coordinator拦截到链接后,更新绑定状态触发Sheet弹出
  • 拦截链接时过滤掉about:blank这类无效URL,只处理真实的外部链接
  • 调用decisionHandler(.cancel)阻止WKWebView默认的跳转行为,确保链接只通过Sheet展示

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 02:12:30