SwiftUI中WKWebView配置代理:监听URL并关闭Sheet+跳转Safari
SwiftUI中WKWebView代理实现与Sheet自动关闭方案
1. 嵌套Coordinator实现代理逻辑
在你的WebView结构体内部定义Coordinator类,它将承担WKWebView的代理职责,同时通过绑定值控制Sheet的显示状态:
import SwiftUI import WebKit struct WebView: UIViewRepresentable { let url: URL // 添加绑定值用于控制Sheet的显示/隐藏 @Binding var isPresented: Bool // 嵌套Coordinator类处理代理 class Coordinator: NSObject, WKNavigationDelegate, WKUIDelegate { private let parent: WebView init(_ parent: WebView) { self.parent = parent } // 处理target="_blank"链接,跳转至Safari func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? { if let url = navigationAction.request.url, UIApplication.shared.canOpenURL(url) { UIApplication.shared.open(url) } return nil } // 监听URL变化,判断是否包含"done"以关闭Sheet func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { guard let currentUrl = webView.url?.absoluteString else { return } if currentUrl.contains("done") { parent.isPresented = false } } } func makeCoordinator() -> Coordinator { Coordinator(self) } func makeUIView(context: Context) -> WKWebView { let webView = WKWebView() // 设置代理为Coordinator webView.navigationDelegate = context.coordinator webView.uiDelegate = context.coordinator return webView } func updateUIView(_ webView: WKWebView, context: Context) { // 避免重复加载相同URL if webView.url?.absoluteString != url.absoluteString { let request = URLRequest(url: url) webView.load(request) } } }
2. 修改Sheet中的WebView调用方式
现在需要将控制Sheet显示的绑定值$showModal传递给WebView,这样代理逻辑就能直接修改该值来关闭Sheet:
struct ContentView: View { @State private var showModal = false var body: some View { Button { showModal.toggle() } label: { Text("**Check ESPN**") } .sheet(isPresented: $showModal, onDismiss: {}) { // 传递isPresented绑定值 WebView(url: URL(string: "https://www.espn.com")!, isPresented: $showModal) } } }
关键说明
- 代理逻辑全部封装在
Coordinator中,它通过持有WebView实例来访问绑定值isPresented,实现Sheet的自动关闭。 - 实现
WKUIDelegate的createWebViewWith方法,拦截target="_blank"的跳转请求,直接调用系统Safari打开链接。 - 实现
WKNavigationDelegate的didFinish方法,在页面加载完成后检查当前URL是否包含"done",如果是则将isPresented设为false关闭Sheet。 updateUIView中增加了URL判断,避免每次状态更新时重复加载相同页面。
内容的提问来源于stack exchange,提问作者J Smooth
相关产品推荐
相关产品推荐

