如何准确判断 WebView 加载完成

原文地址:http://www.jianshu.com/p/897e2d82ee43

正常情况下我们把处理网页加载完毕的代码放在- (void)webViewDidFinishLoad:(UIWebView *)webView 里。但 WebViewDidFinishLoad 时网页真的加载完了吗?

官方文档并没有说明 WebViewDidFinishLoad 到底在什么时候被调用,但事实证明在某些情况下 WebViewDidFinishLoad 可能不是你想要的时机。

网页重定向

当网页重定向发生时,网址被重定向几次,WebViewDidFinishLoad 就会被调用几次。所以如果你只想在最后加载完成时调用某些代码,可以通过webView.isLoading 来判断。当 WebViewDidFinishLoad 时如果 webView.isLoading == YES 那么说明网页可能发生了重定向。

- (void)webViewDidFinishLoad:(UIWebView *)webView {if (!webView.isLoading) {[self webViewDidFinishLoadCompletely];}
}

加载内嵌资源

除了原生方法外,网页的 readyState 属性也可以返回当前加载状态,共有5种。

1、uninitialized : 还没开始加载

2、loading : 加载中

3、loaded : 加载完成

4、interactive : 结束渲染,用户已经可以与网页进行交互。但内嵌资源还在加载中

5、 complete : 完全加载完成

WebViewDidFinishLoad 被调用时,readyState 可能处在 interactive 和 complete 两种状态。当我们需要对网页中的元素进行修改时,最好在 complete 状态进行,不然我们的修改可能被重置。例如百度登录页(http://wappass.baidu.com/passport) 在iPad上打开时,WebViewDidFinishLoad 的 readyState 就是 interactive,这时如果修改输入框里内容(账号密码自动填充),我们的修改将会在 complete 状态时被重置。

为了解决这个问题,我们可以在 WebViewDidFinishLoad 判断 readyState 的状态,如果不是 complete,则重写 window.onload 或者 document.onreadystatechange 两个方法,他们都可以准确判断内嵌资源加载完毕的时机。然后通过 JSExport 回调 Objective-C 代码(如果是 WKWebView 则通过 MessageHandler 回调)。
对 JSExport 还不熟悉可以参考 这篇博客 来简单了解 JSExport 的使用。

- (void)webViewDidStartLoad:(UIWebView *)webView {_jsContext = [_webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];_jsContext[@"xfNewsContext"] = _jsExport;
}- (void)webViewDidFinishLoad:(UIWebView *)webView {if (!webView.isLoading) {NSString *readyState = [webView stringByEvaluatingJavaScriptFromString:@"document.readyState"];BOOL complete = [readyState isEqualToString:@"complete"];if (complete) {[self webViewDidFinishLoadCompletely];} else {NSString *jsString =@"window.onload = function() {"@"    xfNewsContext.onload();"@"};"@"document.onreadystatechange = function () {"@"    if (document.readyState == \"complete\") {"@"        xfNewsContext.documentReadyStateComplete();"@"    }"@"};";[_webView stringByEvaluatingJavaScriptFromString:jsString];}NSLog(@"%@", NSStringFromSelector(_cmd));}
}- (void)onload {[self webViewDidFinishLoadCompletely];NSLog(@"%@", NSStringFromSelector(_cmd));
}- (void)documentReadyStateComplete {[self webViewDidFinishLoadCompletely];NSLog(@"%@", NSStringFromSelector(_cmd));
}- (void)webViewDidFinishLoadCompletely {[self displayContent];
}

在普通网页加载时打印结果是:

1、documentReadyStateComplete

2、 onload

3、webViewDidFinishLoad:

而本例中打印结果则是:

1、webViewDidFinishLoad:

2、documentReadyStateComplete

3、onload

不管 webViewDidFinishLoad 在何时调用,webViewDidFinishLoadCompletely 都保证在加载完成的时候触发。

本文的完整代码可以在 XFNewsContentDemo 中查看。本问与上篇博客共用 Demo,所以 Demo 中有大量与本篇不相关的代码。你只需要找到上述引用代码的部分查看即可。

参考资料

[MDN] document.readyState

[w3schools] HTML DOM readyState Property

[CNBlogs]iOS判断UIWebView加载完成的方法

如何准确判断 WebView 加载完成相关推荐

  1. android 判断webview加载成功,Android:如何检查使用webview.loadUrl时url的成功加载

    不幸的是,目前在WebView中没有简单的方法来确保页面上的所有内容都已成功加载.我们希望在未来的版本中提供更好的API.让我解释一下你现在可以做什么. 首先,为了检测阻止WebView连接服务器加载 ...

  2. 【MFC】在CHtmlView中准确判断页面加载完成

    以前的方法繁琐,这里抄了别人的方法,做了简单修改.记录下. 首先要在CHtmlView的子类中,重载如下函数: virtual void DocumentComplete(LPDISPATCH pDi ...

  3. android判断webview加载完成,android webView判断是否加载完成的2种办法

    =================================== mWebView.setWebViewClient(new WebViewClient() { @Override public ...

  4. Android—WebView加载速度优化工程实践

    一.混合开发的优势与缺陷 在混合开发大行其道的今天,很多页面和功能都转由前端实现,客户端只要在APP中嵌入一个WebView即可,同时前端开发的页面对于Android和iOS端的效果是统一的,省去了适 ...

  5. Android使用WebView加载网页

    在AndroidManifest.xml设置访问网络权限: <span style="font-size:24px;"><span style="fon ...

  6. 利用web实现android的界面,利用WebView加载手机端网页实现APP封装

    **思路 : ** 安卓端只使用一个Activity 此Activity中只包含WebView这个控件 并且隐藏此Activity的标题栏 这样只要我们前端对手机浏览器的适配做的很好 我们这个WebV ...

  7. Android WebView加载完成的监听

    在项目里有时会需要监听WebView加载完成的状态,可能有人会使用WebViewClient里onPageFinished这个方法来监听,可是这个官方的方法到现在还是不稳定,有些能监听到,有些则不能. ...

  8. webview加载的页面和浏览器渲染的页面不一致_QQ音乐Android客户端Web页面通用性能优化实践...

    QQ音乐 Android 客户端的 Web 页面日均 PV 达到千万量级,然而页面的打开耗时与 Native 页面相距甚远,需要系统性优化.本文将介绍 QQ 音乐 Android 客户端在进行 Web ...

  9. webview 加载php页面内容,WebView加载优化的方法介绍

    本篇文章给大家带来的内容是关于WebView加载优化的方法介绍,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. WebView加载优化 当WebView的使用频率变得频繁的时候,对于其 ...

  10. webview加载本地资源的各种尝试

    1.webview 打开sd卡上的静态html文件 ,js文件既然放在assets文件夹下能找到,那能通过放在sd卡,能加载吗? 答:事实证明,是没有用的. 2.既然能拿到html的数据,那我们是不是 ...

最新文章

  1. smc数显压力表设定方法_压力控制器工作原理与设定方法
  2. C#访问Access和Win7 64位下可能遇到的 未在本地计算机上注册“Microsoft.Jet.OLEDB.4.0” 提供程序 问题
  3. python format 字典_python 用字典格式化字符串
  4. lucene.NET详细使用与优化详解
  5. 你买过假芯片吗?元器件专家为您揭秘假冒芯片的套路!
  6. JS-对象-构造函数-实例化-this
  7. greenplum mysql jdbc_Kylin设置JDBC配置greenplum数据源
  8. 登录oracle sql,登录 Oracle SQL Developer
  9. echarts 大屏模板_年会策划万能模板 ,玩转年会看这篇!
  10. java websocket
  11. ContentObserve的基本使用方法
  12. 小班计算机游戏教案,小班游戏简单教案(通用11篇)
  13. pygame 绘制爱心函数 r = 1-cos(θ). Tag: python | 图形界面 | GUI
  14. 毕业设计 高校排课系统
  15. 2018 工作日节假日字典表
  16. Linux桌面环境(桌面系统)大比拼[附带优缺点]
  17. “程序猿”面试篇(一)聊项目
  18. 量化 计算机 金融,金融数据量化分析(上)
  19. C++之getch(),getche(),getchar()的区别
  20. Mn掺杂CdS量子点|锰掺杂硫化镉量子点|MnS/ZnS/CdS量子点的制备方法图示

热门文章

  1. VUE 下载文件错误 Proxy error: Could not proxy request xxx from xxx to xxx. HPE_INVALID_HEADER_TOKEN
  2. [独有源码]springboot医养结合养老APP的设计与实现a7rv0借鉴他人经验,找到适合自己的毕业设计
  3. [Go练习]跳水比赛8个评委打分问题(存在多个最差评委版)
  4. Python 学习日记day 7
  5. nested exception is org.apache.ibatis.binding.BindingException: Parameter 'xxxx' not found. Avai解决办法
  6. PHP-10-mysql
  7. 二维burgers方程_二维Burgers方程的格子Boltzmann模型
  8. idea2020 java - 不能执行jar文件: “no main manifest attribute”的解决办法
  9. npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! webpack_test@1.0.0 dev: `webpack` npm ERR! Exit s
  10. custoj zzj穿裙子 C++