什么时候UIWebView真正加载完成


由于项目需求的原因,要支持iOS 10以前的版本,所以即使WKWebview相比较UIWebview而言,有诸多优点,但暂时还是没法完全舍弃UIWebview。

既然UIWebview有这样那样的缺陷,比如加载消耗内存大,没法实时获取加载进度等;那么也不差再多一个。

WebView什么时候加载完成?

当然是在回调webViewDidFinishLoad:代理方法的时候。这没毛病,毕竟官方文档也是这么解释的。但在实际项目测试中发现,偶尔会出现webViewDidFinishLoad:回调了,但是web资源(比如图片)尚未加载完的情况。

所以,事实是webViewDidFinishLoad回调完成,虽然可以反映浏览器文档解析完成,却不表示资源加载完成

怎么获取资源加载完成的状态?

通过document.readyStatedocument.readyState有三种状态值,详细描述如下。

The readyState property returns three different values.

loading:The browser is loading the document.

interactive:The document has been parsed, but the browser is still loading linked resources.

complete:The document has been parsed and all of the resources have been loaded.

The value of the readyState property moves from loading to interactive to complete.

The readystatechange event is triggered each time the value of the readyState property changes.

<!DOCTYPE HTML>

<html>
<head>
<title>Example</title>
<script>
document.onreadystatechange = function() {
if (document.readyState == “interactive”) {
alert(“results”);
}
}
</script>
</head>
<body>
</body>
</html>

项目中怎么改进?

简单来说,重写document.onreadystatechange方法,最后利用JavaScriptCore,像js交互那样,把结果回调到原生OC函数。

详细参考如下:

// 1 定义交互协议
@protocol JavaScriptObjectiveCDelegate <JSExport>
- (void)documentReadyStateComplete;
@end

// 2 实现交互协议的方法
- (void)documentReadyStateComplete{
    NSLog(@"%@", NSStringFromSelector(_cmd));
}

// 3 对象注入
- (void)webViewDidStartLoad:(UIWebView *)webView{
    __weak typeof(self) weakSelf = self;
    _jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    _jsContext[@"hmhReadyState"] = weakSelf;

    _jsContext.exceptionHandler = ^(JSContext *context, JSValue *exception){
        //异常处理
        NSLog(@"%@",exception);
    };
}

// 4.重写document.onreadystatechange
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    if (!webView.isLoading) {
        NSString *readyState = [webView stringByEvaluatingJavaScriptFromString:@"document.readyState"];
        BOOL complete = [readyState isEqualToString:@"complete"];
        if (complete) {
            [self documentReadyStateComplete];
        } else {
            NSString *jsString =
            @"document.onreadystatechange = function () {"
            @"    if (document.readyState == \"complete\") {"
            @"        hmhReadyState.documentReadyStateComplete();"
            @"    }"
            @"};";
            [_webView stringByEvaluatingJavaScriptFromString:jsString];
        }
        NSLog(@"%@", NSStringFromSelector(_cmd));
    }
}

参考资料:
http://www.cocoachina.com/ios/20170314/18881.html
http://www.java2s.com/Book/JavaScript/DOM/document_readyState.htm

that‘s all!

知识共享许可协议本作品采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可。
本站文章除注明转载/出处外,均为本站原创或翻译,请务必在遵守许可协议的前提下转载。
发布时间:2018-11-27 16:58:51 阅读:840 标签:技术笔记JavaScriptCore