SwiftUI中WKWebView点击返回加载延迟,如何获取加载进度并展示?
实现方案
我们可以通过KVO监听WKWebView自带的estimatedProgress属性获取加载进度,结合@Binding把进度同步到SwiftUI层驱动进度条展示,不管是返回、前进还是首次加载场景都可以自动获取进度,完整修改如下:
1. 修改WebViewForCommunityTab结构体
新增进度绑定属性、KVO监听逻辑和导航代理处理:
import SwiftUI import WebKit import Combine // 监听属性需要用到该库 struct WebViewForCommunityTab : UIViewRepresentable { let request: URLRequest var webview: WKWebView? // 新增绑定属性,用于把加载进度同步到上层View @Binding var loadProgress: Double // 存储KVO监听实例 private var progressObserver: NSKeyValueObservation? init(web: WKWebView?, req: URLRequest, loadProgress: Binding<Double>) { self.webview = WKWebView() self.request = req self._loadProgress = loadProgress } func makeCoordinator() -> Coordinator { Coordinator(self) } func makeUIView(context: Context) -> WKWebView { webview?.navigationDelegate = context.coordinator // 监听WKWebView的加载进度属性 progressObserver = webview?.observe(\.estimatedProgress, options: [.new]) { _, value in DispatchQueue.main.async { self.loadProgress = value.newValue ?? 0 } } return webview! } func updateUIView(_ uiView: WKWebView, context: Context) { uiView.load(request) } func goBack(){ webview?.goBack() } func goForward(){ webview?.goForward() } func goHomeScreen(){ webview?.load(URLRequest(url: (URL(string: DefaultUrlString.CommunityWebLink)!))) } // 新增Coordinator处理WKWebView导航代理事件 class Coordinator: NSObject, WKNavigationDelegate { var parent: WebViewForCommunityTab init(_ parent: WebViewForCommunityTab) { self.parent = parent } // 页面加载完成后重置进度,隐藏进度条 func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { DispatchQueue.main.async { self.parent.loadProgress = 0 } } // 页面加载失败也重置进度 func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) { DispatchQueue.main.async { self.parent.loadProgress = 0 } } } }
2. 修改WebContentView添加进度条展示
新增状态变量存储加载进度,在WebView顶部插入进度条:
struct WebContentView: View { // 存储加载进度的状态变量,取值范围0~1 @State private var loadProgress: Double = 0 // 初始化WebView时传入进度绑定 let webview = WebViewForCommunityTab(web: nil, req: URLRequest(url: URL(string: DefaultUrlString)!), loadProgress: $loadProgress) var body: some View { ZStack { VStack(spacing: 0) { // 仅加载过程中显示进度条 if loadProgress > 0 && loadProgress < 1 { ProgressView(value: loadProgress, total: 1) .progressViewStyle(LinearProgressViewStyle(tint: .blue)) .frame(height: 2) } webview HStack (alignment: .center) { Group { Spacer() CustomButtonForWebView(btnImageTitle: ArrowLeftCircleImg, action: { self.webview.goBack() }) CustomButtonForWebView(btnImageTitle: ArrowRightCircleImg, action: { self.webview.goForward() }) Spacer() }.padding(.bottom,10) }.frame(width: UIScreen.main.bounds.width, height: 40, alignment: .center) }.hiddenNavigationBarStyle().background(Color.white) } } }
逻辑说明
WKWebView的estimatedProgress是系统维护的0~1之间的浮点数,代表当前页面的加载进度,返回、前进、刷新、首次加载等所有页面跳转场景都会自动更新该值- 通过KVO监听该属性,把进度值同步到SwiftUI的状态变量,即可驱动进度条实时更新
- 页面加载完成/失败后重置进度为0,进度条会自动隐藏
内容的提问来源于stack exchange,提问作者Sham Dhiman
相关产品推荐
相关产品推荐

