如何在 SwiftUI 中观察 WKWebView 的加载进度?

Posted

技术标签:

【中文标题】如何在 SwiftUI 中观察 WKWebView 的加载进度?【英文标题】:How to observe loading progress for WKWebView in SwiftUI? 【发布时间】:2020-09-21 04:36:37 【问题描述】:

我正在使用 SwiftUI 构建一个 Web 浏览器,并将视图分为 3 个部分:SearchView、WebView (UIViewRepresentable)。

在 SearchView 中,我有 @Binding var query,它在 TextField 的 onCommit 方法上得到更新。 WebView 有@Binding var query@Binding var loadingProgress。当查询和进度都更新时,正确知道 webView 更新。如何过滤这些事件并且不重新加载 webView 以进行进度更改?

我想我需要使用updateUIView(_ uiView: WKWebView, context: Context) 方法,但我不知道如何实现这个逻辑。或者也许所有的概念都是错误的?

这是我的网页视图

struct BrowserWebView: UIViewRepresentable 
    
var webView = WKWebView()

@Binding var query: String
@Binding var loadingProgress: Float

func makeUIView(context: Context) -> WKWebView 
    context.coordinator.addProgressObserver()
    webView.navigationDelegate = context.coordinator
    return webView


func updateUIView(_ uiView: WKWebView, context: Context) 
    loadQuery()


private func loadQuery() 
    guard let url = URL(string: query) else  return 
    let request = URLRequest(url: url)
    webView.load(request)


func makeCoordinator() -> Coordinator 
    return Coordinator(self)


class Coordinator: NSObject, WKNavigationDelegate 
    var parent: BrowserWebView
    
    init(_ parent: BrowserWebView) 
        self.parent = parent
    
    
    func addProgressObserver() 
        parent.webView.addObserver(self, forKeyPath: #keyPath(WKWebView.estimatedProgress), options: .new, context: nil)
    
    
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) 
        if let o = object as? WKWebView, o == parent.webView 
            if keyPath == #keyPath(WKWebView.estimatedProgress) 
                parent.loadingProgress = Float(parent.webView.estimatedProgress)
            
        
    
  

在外面我有更新 ProgressView 的 @State 属性

【问题讨论】:

【参考方案1】:

您可以简单地将 webview 的当前 url 字符串与查询进行比较以跳过重新加载,例如:

func updateUIView(_ uiView: WKWebView, context: Context) 
    guard let url = URL(string: query) else  return 
    if uiView.url == nil || uiView.url?.absoluteString.trimmingCharacters(in: CharacterSet(arrayLiteral: "/")) != query 
        let request = URLRequest(url: url)
        uiView.load(request)
    

【讨论】:

以上是关于如何在 SwiftUI 中观察 WKWebView 的加载进度?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 SwiftUI 中为 WKWebView 创建浏览器选项卡

如何在 SwiftUI 中创建一个列表视图,每个列表项都是一个 WKWebView(我的实现非常慢并且有问题)

SwiftUI 中的 WKWebView - 用户与网站交互时如何切换视图?

如何在 WKWebview 中添加观察者以播放和暂停音频文件的操作?

如何阻止 SwiftUI 重新加载我通过 UIViewRepresentable 使用的 WKWebView 页面?

SwiftUI WebKit WKWebView:如何支持多 url