每次检测 WKWebView 何时完成加载

Posted

技术标签:

【中文标题】每次检测 WKWebView 何时完成加载【英文标题】:Detect when WKWebView has finished loading EVERY time 【发布时间】:2015-04-13 10:21:34 【问题描述】:

我有一个在 iPad 上的 ios8 上运行的 WKWebView 应用程序(标准 iPad UserAgent:“Mozilla/5.0 (iPad; CPU OS 8_1_1 like Mac OS X) AppleWebKit/600.1.4 (Khtml, like Gecko) Version/8.0 Mobile/12B436 Safari/600.1.4")。我已经尝试了所有我能想到的委托和侦听器,每次都尝试检测页面何时完成加载。问题来了:

    打开您的 WKWebView 并转到 Google。调用如下:

    _decidePolicyForNavigationAction
    _didStartProvisionalNavigation
    _ didFinishNavigation
    

    在 Google 中输入“YouTube”: 仅调用 _decidePolicyForNavigationAction。没有 didStartProvisionalNavigation 或 didFinishNavigation

    在 Google 中点击 YouTube。调用如下:

    _didStartProvisionalNavigation
    _decidePolicyForNavigationAction
    _ didFinishNavigation
    

    从现在开始,在 YouTube 中什么都不会调用。单击 YouTube 视频,没有 didStartProvisionalNavigation 或 didFinishNavigation。此外,不再调用 webview.loading 观察者。甚至decisionPolicyForNavigationAction 也只是时不时地被调用。但是... webView.backForwardList.currentItem 在每次点击后都会更新,所以这一定是在检测页面何时以某种方式完成加载?

这种行为也发生在许多其他网站上(例如 Vimeo)。我知道这种类型的网站不会每次都更新主框架,但这是否缺乏检测加载何时开始/完成的能力是 WKWebView 在其当前状态下的“限制”?

我想要实现的是:是否有另一种方法来检测导航何时完成,每次在 YouTube/Vimeo 等 Java 移动网站中

使用 NSURLProtocol 或类似的? 或者也许是一种检测何时 webView.backForwardList.currentItem 更新了吗?

感谢您的帮助。

【问题讨论】:

查看***.com/questions/32660051/… 我使用 webview.scrollView.contentSize 属性来检查高度,如果它为零,那么我会在设置之前稍稍延迟调用相应的函数。 谢谢,但我不想检测 WKWebView 何时出现在屏幕上 - 我希望 WKWebView 在仅使用 Java 的网站(YouTube 移动设备、Vimeo 移动设备等)开始和结束加载时通知我在 iPhone 上的网站内点击。在 iPhone 上加载 YouTube 后,WKWebView 不会调用任何东西...您可以继续浏览该网站,并且不会调用任何委托方法。 Web 视图的问题在于,对于您无法控制的网站(因此可以插入特定的事件挂钩),一旦您开始尝试,“完成加载”的概念就开始变得非常难以定义一般把它固定下来。 javascript 在页面中加载和运行是现代复杂网站的典型特征,它可以通过非页面请求拉取内容,然后在原始 HTML 及其资源完全下载并构建 DOM 后填充页面。这就是您在 YT 和 Vimeo 中看到的。从技术上讲,该页面无法在任何地方导航。 快速解决方案:***.com/a/40730365/4488252 【参考方案1】:

我不确定页面加载后您到底想做什么,但希望观察这些属性可以帮助您:

webView.addObserver(self, forKeyPath: "estimatedProgress", options: .New, context: nil)
webView.addObserver(self, forKeyPath: "loading", options: .New, context: nil)
webView.addObserver(self, forKeyPath: "title", options: .New, context: nil)
webView.addObserver(self, forKeyPath: "canGoBack", options: .New, context: nil)
webView.addObserver(self, forKeyPath: "canGoForward", options: .New, context: nil)

【讨论】:

这是唯一对我有用的东西——对估计的进度做出反应。有时即使 wkwebview 进度不是 1 并且文档显然仍在加载,也会调用 jquery ready。 上面有没有基于观察者触发方法的demo代码? 非常感谢;这对我帮助很大!但为了完全可靠,我必须将“URL”添加到观察到的键路径列表中!【参考方案2】:

如果有人正在寻找如何使用观察者的解决方案,这里是解决方案:

webView.addObserver(self, forKeyPath: "title", options: .new, context: nil);
webView.addObserver(self, forKeyPath: "loading", options: .new, context: nil);
webView.addObserver(self, forKeyPath: "estimatedProgress", options: .new, context: nil);

然后使用observeValue函数并编写一个switch-case或if-else来找到keyPath

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) 
    if keyPath == "title" 
        print(change ?? "No title")
        if change != nil, let currentTitle = change?[.newKey] as? String 
            titleLabel.text = currentTitle
        
     else if keyPath == "loading" 
        print("Loading")
        reloadButton.setImage(#imageLiteral(resourceName: "cancel.png"), for: .normal)
     else if keyPath == "estimatedProgress" 
        print(wkWebView.estimatedProgress);
        progressView.progress = Float(wkWebView.estimatedProgress)
    

Here我创建了一个演示项目来探索更多关于 WebKit WebView 的信息。

【讨论】:

以上是关于每次检测 WKWebView 何时完成加载的主要内容,如果未能解决你的问题,请参考以下文章

检测用户何时点击加载在 UIWebView 或 WKWebView 中的 web 表单

检测 WKWebView 中的非导航按钮单击

如何检测 amp 页面的 url 何时随 WKWebview 更改

检测用户何时向左或向右滑动以在 WKWebView 上前后移动

WKWebView:应用程序因“NSInternalInconsistencyException”异常而崩溃,因为“未调用传递给 X 的完成处理程序”

iOS WKWebview如何检测我何时点击<a>标签内的图像