close
当前位置: 物联网在线 > 技术文库 > ios >

如何准确判断 WebView 加载完成

正常情况下我们把处理网页加载完毕的代码放在 - (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种。

uninitialized : 还没开始加载

loading : 加载中

loaded : 加载完成

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

complete : 完全加载完成

WebViewDidFinishLoad 被调用时,readyState 可能处在 interactive 和 complete 两种状态。当我们需要对网页中的元素进行修改时,最好在 complete 状态进行,不然我们的修改可能被重置。例如百度登录页在iPad上打开时,WebViewDidFinishLoad 的 readyState 就是 interactive,这时假设想要在输入框里自动填写账号密码并修改输入框背景为黄色,我们的修改将会在 complete 状态时被重置。

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

- (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]; }

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

documentReadyStateComplete

onload

webViewDidFinishLoad:

而本例中打印结果则是:

webViewDidFinishLoad:

documentReadyStateComplete

onload

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

参考资料

[MDN] document.readyState

[w3schools] HTML DOM readyState Property

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


(责任编辑:ioter)

用户喜欢...

电源管理集成电路(PMIC)如何减少这些挑战的影响

在设计具有现场可编程门阵列(FPGA)的系统时,系统设计人员可以获得三个好处:可重编程性,性能可扩展性和快速上市时间。但是,设计师也必须克服挑战。在这篇文章中,我将讨论电源管...


为了提高效率 - 如何将双向功率流集成到UPS设计中(第2部分)

在本系列的第1部分中,我讨论了如何将双向功率流集成到不间断电源(UPS)设计中。在第二部分中,我将更详细地介绍用于UPS和电池备份应用的2kW,48V至400V, 93%效率,隔离双向DC / DC转换器参...


为了提高效率 - 如何将双向功率流集成到UPS设计中(第1部分)

随着对更紧凑,更小和更高效的电力系统的日益重视,对双向转换器的兴趣日益增加。能够双向功率流的双向DC / DC转换器可以将传统上用于电池充电和备份操作所需的两个DC / DC转换器组合成一...


如何为高性能、低侧电流传感设计电路板?

在我以前的 博客帖子 我讨论了低侧电流传感如何帮助控制电机,然后给出了设计低侧电流传感电路的三个步骤,以适用于成本敏感的应用。在这篇文章中,我将讨论如何使用正确的印刷电路板...


如何设计-130-dB超低失真数据采集系统

数据采集​​系统(DAS)是工业,医疗和电信应用的标准测量和分析仪器,包括医学成像,音频和振动分析以及模拟和数字调制系统的测试。在大多数情况下,采集和数字化信号通过快速傅里叶...


自主汽车传感器:处理器算法如何获得输入

尽管鉴于最近特斯拉级别S的死亡,有关自主汽车消亡的非技术性媒体报道,我想在本文中介绍传感器电子设备,结合更好和更精细的软件算法,最终将实现在未来十年内,一辆安全,完全自主...


如何设计电感式触摸金属按钮面板

人机界面(HMI)正在经历地震变化,现在有一种新方法可用于设计按钮面板。在创建金属触摸(ToM)按钮时,电感式传感技术正成为首选方法。主要原因是它可以降低成本,同时更加可靠,因为...


ams ENS210相对湿度与温度传感器集成湿度传感器与高准确度温度传感器

ams ENS210相对湿度与温度传感器集成湿度传感器与高准确度温度传感器,采用 QFN4 封装。 ENS210内含一个I 2 C从属接口,用于与主处理器通信。 ENS210作业温度范围介于-40C至100C,作业相对湿度范围...


如何为RF应用选择,使用和维护同轴连接器

无线电频率(RF)电路在有线和无线通信中正在激增,包括用于物联网(IoT)的Wi-Fi和各种无线技术。这些高频信号需要在系统,电路组件和子组件之间进行分配,而损耗或寄生辐射损耗最小。...


制造商和工程师:了解您的仪表放大器以实现准确的物联网数据采集

感知是物联网(IoT)和智能家居开始的地方,也是DIY爱好者,制造者甚至专业设计师遇到他们的第一个问题的地方。许多便宜的传感器,如加速计,力传感器,应变计和压力传感器都是围绕电...