UIWebView:什么时候页面真的完成加载?

我需要知道,当一个网页已完全由UIWebView加载。 我的意思是,当所有redirect完成并且dynamic加载的内容已经准备就绪的时候。 我尝试注入JavaScript(查询document.readyState == 'complete' ),但这似乎不是很可靠。

有没有,也许,从私人api会给我带来的结果吗?

我一直在寻找答案,我从塞巴斯蒂安的问题中得到了这个想法。 不知何故,它对我有用,也许会遇到这个问题的人。

我设置了一个委托给UIWebView和在webViewDidFinishLoad,我检测如果webview已经真的完成加载通过执行一个Javascript。

 - (void)webViewDidFinishLoad:(UIWebView *)webView { if ([[webView stringByEvaluatingJavaScriptFromString:@"document.readyState"] isEqualToString:@"complete"]) { // UIWebView object has fully loaded. } } 

我的解决scheme

 - (void)webViewDidFinishLoad:(UIWebView *)webView { if (!webView.isLoading) { // Tada } } 

UIWebView执行Javascript的能力与页面是否加载无关。 它可能的用法stringByEvaluatingJavaScriptFromString:执行Javascript之前,你甚至已经打电话来加载页面在UIWebView首先,或者根本没有加载页面。

所以我不明白如何接受这个链接的答案: webViewDidFinishLoad:发射太快? 因为调用任何 Javascript并不会告诉你什么(如果他们正在调用一些有趣的Javascript,例如监视dom,他们不会提及这个,如果有的话,因为它的重要性)。

例如,您可以调用一些Javascript来检查dom的状态或加载的页面的状态,然后将其返回给调用代码,但是如果报告页面尚未加载,那么您会怎么做? – 你将不得不稍后再调用它,但是多less时间,何时,何地,多less次,多less次……投票通常不是一个好的解决scheme。

要知道什么时候页面已经完全加载并且准确无误,并且要掌握如何自己完成它的唯一方法 – 将JavaScript事件监听器附加到正在加载的页面中,并让他们调用您的shouldStartLoadWithRequest:url。 你可以,例如,创build一个JS函数来侦听窗口加载或dom就绪事件等,这取决于你是否需要知道页面何时加载,或者只是dom已经加载等等。根据你的需要。

如果网页不是你的,那么你可以把这个JavaScript放入一个文件,并将其注入到您加载的每个页面中。

如何创buildJavaScript事件监听器是标准的JavaScript,没有什么特别与iOS做的,例如这里是JavaScript检测何时加载了一个表单,可以从UIWebView内注入到加载页面,然后导致调用shouldStartLoadWithRequest:(这将调用shouldStartLoadWithRequestwhen:dom已经完成了loadeding,这是整个页面内容已经显示,检测这只是改变事件监听器)。

 var script = document.createElement('script'); script.type = 'text/javascript'; script.text = function DOMReady() { document.location.href = "mydomain://DOMIsReady"; } function addScript() { document.getElementsByTagName('head')[0].appendChild(script); document.addEventListener('DOMContentLoaded', DOMReady, false); } addScript(); 

马丁H的回答是正确的,但它仍然可以被解雇多次。

你需要做的是在页面上添加一个Javascript onLoad监听器,并跟踪你是否已经插入了监听器:

 #define kPageLoadedFunction @"page_loaded" #define kPageLoadedStatusVar @"page_status" #define kPageLoadedScheme @"pageloaded" - (NSString*) javascriptOnLoadCompletionHandler { return [NSString stringWithFormat:@"var %1$@ = function() {window.location.href = '%2$@:' + window.location.href; window.%3$@ = 'loaded'}; \ \ if (window.attachEvent) {window.attachEvent('onload', %1$@);} \ else if (window.addEventListener) {window.addEventListener('load', %1$@, false);} \ else {document.addEventListener('load', %1$@, false);}",kPageLoadedFunction,kPageLoadedScheme,kPageLoadedStatusVar]; } - (BOOL) javascriptPageLoaded:(UIWebView*)browser { NSString* page_status = [browser stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"window.%@",kPageLoadedStatusVar]]; return [page_status isEqualToString:@"loaded"]; } - (void)webViewDidFinishLoad:(UIWebView *)browser { if(!_js_load_indicator_inserted && ![self javascriptPageLoaded:browser]) { _js_load_indicator_inserted = YES; [browser stringByEvaluatingJavaScriptFromString:[self javascriptOnLoadCompletionHandler]]; } else _js_load_indicator_inserted = NO; } 

当页面加载完成时,Javascript监听器将触发URL pageloaded:<URL that actually finished>加载的新页面加载pageloaded:<URL that actually finished> 。 然后,您只需要更新shouldStartLoadWithRequest来查找该URLscheme:

 - (BOOL)webView:(UIWebView *)browser shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { if([request.URL.scheme isEqualToString:kPageLoadedScheme]){ _js_load_indicator_inserted = NO; NSString* loaded_url = [request.URL absoluteString]; loaded_url = [loaded_url substringFromIndex:[loaded_url rangeOfString:@":"].location+1]; <DO STUFF THAT SHOULD HAPPEN WHEN THE PAGE LOAD FINISHES.> return NO; } } 

你也可以在这里使用接受的答案: UIWebView – 如何识别“最后”webViewDidFinishLoad消息? …

基本上,使用estimatedProgress属性,当达到100时,页面已完成加载…请参阅本指南以获取帮助。

虽然它使用私人框架,根据指南 ,在App Store中有一些应用程序使用它…

让您的View Controller成为UIWebView的代表。 (您可以在Interface Builder中执行此操作,也可以在viewDidLoad方法中使用此代码:

 [self.myWebView setDelegate:self]; 

然后使用接受的答案中描述的方法在这里: webViewDidFinishLoad:发射太快? 。

代码:

 -(void) webViewDidFinishLoad:(UIWebView *)webView { NSString *javaScript = @"function myFunction(){return 1+1;}"; [webView stringByEvaluatingJavaScriptFromString:javaScript]; //Has fully loaded, do whatever you want here } 

这是@jasonjwwilliams答案的简化版本。

 #define JAVASCRIPT_TEST_VARIBLE @"window.IOSVariable" #define JAVASCRIPT_TEST_FUNCTION @"IOSFunction" #define LOAD_COMPLETED @"loaded" // Put this in your init method // In Javascript, first define the function, then attach it as a listener. _javascriptListener = [NSString stringWithFormat: @"function %@() {\ %@ = '%@';\ };\ window.addEventListener(\"load\", %@, false);", JAVASCRIPT_TEST_FUNCTION, JAVASCRIPT_TEST_VARIBLE, LOAD_COMPLETED, JAVASCRIPT_TEST_FUNCTION]; // Then use this: - (void)webViewDidFinishLoad:(UIWebView *)webView; { // Only want to attach the listener and function once. if (_javascriptListener) { [_webView stringByEvaluatingJavaScriptFromString:_javascriptListener]; _javascriptListener = nil; } if ([[webView stringByEvaluatingJavaScriptFromString:JAVASCRIPT_TEST_VARIBLE] isEqualToString:LOAD_COMPLETED]) { NSLog(@"UIWebView object has fully loaded."); } } 

由于JavaScript,新的资源和新的graphics可以永久加载 – 确定何时加载完成,对于一个足够扭曲的页面,将等于解决停止问题 。 你真的不知道何时加载页面。

如果可以的话,只需显示页面或其图像,然后使用webViewDidLoad更新图像,并让用户决定何时切断或不切断。