每次加载页面中的任何对象时,似乎都会发送webViewDidFinishLoad消息。有没有办法确定所有内容加载都已完成?
答案 0 :(得分:60)
我猜iframe会导致webViewDidStartLoad
/ webViewDidFinishLoad
对。
作为答案提到的[webView isLoading]
检查对我不起作用;即使在两次false
次呼叫中的第一次呼叫后,它也会返回webViewDidFinishLoad
。相反,我按如下方式跟踪加载:
- (void)webViewDidStartLoad:(UIWebView *)webView {
webViewLoads_++;
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
webViewLoads_--;
if (webViewLoads_ > 0) {
return;
}
…
}
- (void)webView:(UIWebView*)webView didFailLoadWithError:(NSError*)error {
webViewLoads_--;
}
(注意这只有在开始/结束对不是连续出现的情况下才有效,但根据我的经验到目前为止还没有发生过。)
答案 1 :(得分:19)
检查一下,它肯定适合你:
- (void)webViewDidFinishLoad:(UIWebView *)webView {
if ([[webView stringByEvaluatingJavaScriptFromString:@"document.readyState"] isEqualToString:@"complete"]) {
// UIWebView object has fully loaded.
}
}
答案 2 :(得分:9)
有趣的是,我不会认为它会像那样工作。虽然我确定还有其他方法可以做到这一点(有没有办法从webViewDidFinishLoad消息中提取URL,以便您可以看到哪一个是主页完成加载?),我能想到的主要是使用estimatedProgress检查页面的进度,并在100%完成加载时触发你要做的任何事情,这就是我在我的应用程序中所做的。谷歌“iphone webview estimatedprogress”,点击我写的关于如何做这个指南的第一个链接。
更新
请使用下面的phopkins答案代替我的!在您的应用程序中使用私有API是一个坏主意,您可能会被拒绝,他的解决方案是正确的。
答案 3 :(得分:1)
使用较少控制来监视加载进度的另一种方法是观察WebViewProgressEstimateChangedNotification,WebViewProgressFinishedNotification和WebViewProgressStartedNotification通知。例如,您可以观察这些通知,以在您的应用程序中实现简单的进度指示器。 您可以通过调用estimatedProgress方法来更新进度指示器,以估算当前加载的内容量。
答案 4 :(得分:1)
你也可以使用我编写的这个简短的类别,它将块添加到UIWebView中,并且还允许您在默认UIWebView行为(在每个对象加载后得到通知)或“预期”行为之间进行选择(仅在页面完全通知时获得通知)加载)。
答案 5 :(得分:1)
我需要从尚未完全加载的页面中捕获变量。
这对我有用:
- (void) webViewDidFinishLoad:(UIWebView *)webView {
NSString *valueID = [webView stringByEvaluatingJavaScriptFromString:@"document.valueID;"];
if([valueID isEqualToString:@""]){
[webView reload];
return;
}
//page loaded
}
答案 6 :(得分:1)
所有选项都不适用于我的用例。我用phopkins的例子略加修改。我发现,如果加载到webview中的HTML包含的图像是一个连续发生的单独请求,那么我们必须考虑到这一点,我用计时器做了。不是最好的解决方案,但似乎有效。:
- (void)webViewActuallyFinished {
_webViewLoads--;
if (_webViewLoads > 0) {
return;
}
//Actually done loading
}
- (void)webViewDidStartLoad:(UIWebView *)webView {
_webViewLoads++;
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
[NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(webViewActuallyFinished) userInfo:nil repeats:NO];
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
_webViewLoads--;
}
答案 7 :(得分:0)
嗨,它可能已经有点远,但我希望这会有所帮助。
我只是在进入webViewDidFinishLoad方法时使用了通知,这样我就可以捕获该方法的一个实例,然后我将检测通知并从那里开始我的逻辑。
希望这会有所帮助。它不会捕获webViewDidFinishLoad方法的最后一个被调用的实例,但允许您在调用后执行某些操作,而不是重复调用该特定方法(例如,显示按钮)。的 强> 的 ** * ** * *** 强> 修改的 * ** * ** * ** 强>
我做了一个测试并设法测试了它。它实际上是有效的,并且在加载完整页面后将调用从通知中调用的方法。
或者,我认为你可以在委托方法webViewDidStartLoad和webViewDidFinishLoad上做一个计数器,以确保在运行代码之前它们是相同的。虽然这是一个丑陋的黑客,因为我们永远不会知道它将被调用多少次,除非像我一样,你正在加载一个html提要并且可以添加一个JavaScript来检查你正在加载的页面上有多少元素。我只是分享了我试图解决的一些方法。希望它有所帮助。
鼓励反馈。谢谢!答案 8 :(得分:0)
这是我在DOM加载时用来显示微调器的内容,建立在@Vinod的答案之上。
请注意,webViewDidStartLoad
和webViewDidFinishLoad
之间 readyState 已完成来自之前的请求(如果有),这就是为什么轮询应该在webViewDidFinishLoad
之后开始。
readyState 可能的值是加载,交互式或已完成(也许 nil >?)
- (void)webViewDidStartLoad:(UIWebView *)webView {
[self spinnerOn];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
[self startDOMCompletionPolling];
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
[self startDOMCompletionPolling];
}
- (void)startDOMCompletionPolling {
if (self.domCompletionListener) {
[self.domCompletionListener invalidate];
}
self.domCompletionListener = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(checkDOMCompletion) userInfo:nil repeats:YES];
}
- (void)checkDOMCompletion {
NSString *readyState = [self.webView stringByEvaluatingJavaScriptFromString:@"document.readyState"];
if (readyState != nil) {
if (readyState.length > 0) {
if ([readyState isEqualToString:@"loading"]) { //keep polling
return;
}
}
}
//'completed', 'interactive', nil, others -> hide spinner
[self.domCompletionListener invalidate];
[self spinnerOff];
}
答案 9 :(得分:-6)
我这样做是这样的:
- (void)webViewDidFinishLoad:(UIWebView *)webview {
if (webview.loading)
return;
// now really done loading code goes next
[logic]
}