SwiftUI中UIViewRepresentable包装WKWebView隐藏默认加载文本
问题
通过UIViewRepresentable实现SViewerWebView组件,用于加载携带Authorization请求头的网页,通过@Binding的isLoading状态控制自定义ProgressView显示。但加载过程中,自定义加载视图消失后、网页内容显示前,WKWebView会显示默认的"Loading..."文本,如何隐藏该默认文本?
原组件代码:
struct SViewerWebView: UIViewRepresentable{ var url: String var token: String @Binding var isLoading: Bool func makeCoordinator() -> Coordinator { Coordinator(self) } func makeUIView(context: Context) -> WKWebView { let webConfiguration = WKWebViewConfiguration() let webView = WKWebView(frame:.zero,configuration:webConfiguration) webView.allowsBackForwardNavigationGestures = true webView.isInspectable = true webView.navigationDelegate = context.coordinator return webView } func updateUIView(_ uiView: WKWebView, context: Context) { guard let urlforRequest = URL(string: url) else { print("❌ Invalid URL:", url) return } var request = URLRequest(url: urlforRequest) request.addValue("Bearer \(token)", forHTTPHeaderField: "Authorization") print("🔄 Loading URL:", url) print("🛠 Headers:", request.allHTTPHeaderFields ?? [:]) uiView.load(request) } //coordinator class Coordinator: NSObject, WKNavigationDelegate { var parent: SViewerWebView init(_ parent: SViewerWebView) { self.parent = parent } func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { DispatchQueue.main.async { self.parent.isLoading = false // Hide loading when page loads } } func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) { DispatchQueue.main.async { self.parent.isLoading = false // Hide loading on error } } } }
视图层代码:
var body: some View { ZStack{ SViewerWebView(url: webUrl,token: TokenManager.getToken()!,isLoading: $isLoading) if isLoading{ VStack { ProgressView() .progressViewStyle(CircularProgressViewStyle()) .scaleEffect(1.5) } .frame(maxWidth: .infinity, maxHeight: .infinity) .background(Color.white) } } .ignoresSafeArea() }
解决方案
核心是通过初始加载空白页面避免默认"Loading..."文本,同时延迟或监听加载进度确保自定义加载视图在网页内容完全渲染后再隐藏,消除中间的空白过渡问题。
修改步骤:
- 初始加载空白页面:在
makeUIView中给WKWebView加载空白HTML,替换默认的加载提示 - 优化加载状态时机:延迟隐藏加载视图,或监听加载进度确保内容渲染完成
- 避免重复加载:在
updateUIView中判断当前URL是否与要加载的一致,防止重复请求
修改后的完整代码:
struct SViewerWebView: UIViewRepresentable{ var url: String var token: String @Binding var isLoading: Bool func makeCoordinator() -> Coordinator { Coordinator(self) } func makeUIView(context: Context) -> WKWebView { let webConfiguration = WKWebViewConfiguration() let webView = WKWebView(frame:.zero,configuration:webConfiguration) webView.allowsBackForwardNavigationGestures = true webView.isInspectable = true webView.navigationDelegate = context.coordinator // 初始加载空白页面,避免默认Loading文本 webView.loadHTMLString("", baseURL: nil) // 监听加载进度,确保内容完全渲染 webView.addObserver(context.coordinator, forKeyPath: #keyPath(WKWebView.estimatedProgress), options: .new, context: nil) return webView } func updateUIView(_ uiView: WKWebView, context: Context) { guard let urlforRequest = URL(string: url), uiView.url != urlforRequest else { print("❌ Invalid URL or same URL:", url) return } var request = URLRequest(url: urlforRequest) request.addValue("Bearer \(token)", forHTTPHeaderField: "Authorization") print("🔄 Loading URL:", url) print("🛠 Headers:", request.allHTTPHeaderFields ?? [:]) // 开始加载时显示自定义加载视图 DispatchQueue.main.async { self.isLoading = true } uiView.load(request) } //coordinator class Coordinator: NSObject, WKNavigationDelegate { var parent: SViewerWebView init(_ parent: SViewerWebView) { self.parent = parent } deinit { // 移除KVO监听,避免内存泄漏 if let webView = parent.makeUIView(context: Context()) as? WKWebView { webView.removeObserver(self, forKeyPath: #keyPath(WKWebView.estimatedProgress)) } } override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { if keyPath == #keyPath(WKWebView.estimatedProgress), let progress = change?[.newKey] as? Double { DispatchQueue.main.async { // 加载进度达到100%时隐藏加载视图 if progress >= 1.0 { self.parent.isLoading = false } } } } func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { // 作为 fallback,导航完成后延迟隐藏,确保内容渲染 DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { self.parent.isLoading = false } } func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) { DispatchQueue.main.async { self.parent.isLoading = false } } } }
说明:
- 初始空白页面直接覆盖了
WKWebView的默认加载提示,避免加载初期显示"Loading..." - KVO监听
estimatedProgress可以精准捕捉加载完成的时机,确保网页内容已渲染 didFinish回调中延迟0.1秒作为兜底,避免进度监听失效的情况updateUIView中的URL判断防止重复触发加载请求
内容的提问来源于stack exchange,提问作者MiguelG
相关产品推荐
相关产品推荐

