UIWebView – Como identificar a “última” mensagem webViewDidFinishLoad?

A mensagem webViewDidFinishLoad parece ser enviada toda vez que qualquer object da página for carregado. Existe uma maneira de determinar que todo o carregamento de conteúdo é feito?

Interessante, eu não teria pensado que funcionaria assim. Embora eu tenha certeza de que existem outras maneiras de fazer isso (existe uma maneira de extrair a URL da mensagem webViewDidFinishLoad para que você possa ver qual deles é o carregamento final da página principal?), A principal coisa que posso pensar é usar o Progresso estimado para verificar o progresso da página e triggersr o que você quiser fazer quando estiver 100% concluído o carregamento, que é o que eu faço no meu aplicativo. Google “iphone webview estimatedprogress” e clique no primeiro link para um guia que escrevi sobre como fazer isso.

Atualizar:

Por favor, use a resposta de phopkins abaixo em vez da minha! Usar APIs privadas em seus aplicativos é uma má ideia e você provavelmente será rejeitado, e a solução dele é a correta.

Eu estou supondo que iframes causam o par webViewDidFinishLoad / webViewDidFinishLoad .

A verificação [webView isLoading] mencionada como uma resposta não funcionou para mim; Ele retornou false mesmo após a primeira de duas chamadas webViewDidFinishLoad . Em vez disso, acompanho o carregamento da seguinte forma:

 - (void)webViewDidStartLoad:(UIWebView *)webView { webViewLoads_++; } - (void)webViewDidFinishLoad:(UIWebView *)webView { webViewLoads_--; if (webViewLoads_ > 0) { return; } … } - (void)webView:(UIWebView*)webView didFailLoadWithError:(NSError*)error { webViewLoads_--; } 

(Observe que isso só funcionará se os pares de início / término não vierem em série, mas na minha experiência até agora isso não aconteceu.)

Marque esta, definitivamente vai funcionar para você:

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

Outra maneira de monitorar o progresso da carga com menos controle é observar as notifications de WebViewProgressEstimateChangedNotification, WebViewProgressFinishedNotification e WebViewProgressStartedNotification. Por exemplo, você pode observar essas notifications para implementar um indicador de progresso simples em seu aplicativo. Você atualiza o indicador de progresso chamando o método estimatedProgress para obter uma estimativa da quantidade de conteúdo atualmente carregada.

de http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/WebKit/Classes/WebView_Class/Reference/Reference.html

Você também pode usar essa pequena Categoria I que adiciona blocos ao UIWebView e também permite escolher entre o comportamento padrão do UIWebView (ser notificado após cada carregamento de object) ou o comportamento “esperado” (ser notificado somente quando a página estiver totalmente carregada).

https://github.com/freak4pc/UIWebView-Blocks

Eu precisava capturar uma variável da página que ainda não estava totalmente carregada.

Isso funcionou para mim:

 - (void) webViewDidFinishLoad:(UIWebView *)webView { NSString *valueID = [webView stringByEvaluatingJavaScriptFromString:@"document.valueID;"]; if([valueID isEqualToString:@""]){ [webView reload]; return; } //page loaded } 

Todas as opções realmente não funcionaram no meu caso de uso. Eu usei phopkins exemplo ligeiramente modificado. Descobri que, se o HTML carregado na visualização da Web contivesse uma imagem que seria uma solicitação separada que aconteceu em série, temos que contabilizar isso e eu fiz isso com um timer. Não é a melhor solução, mas parece funcionar.

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

oi pode ser um pouco longe já, mas espero que isso ajude.

Acabei de usar uma notificação quando ela insere o método webViewDidFinishLoad para que eu possa capturar uma instância do método e, em seguida, detectarei a notificação e executarei minha lógica a partir dela.

espero que isto ajude. ele não captura a última instância chamada do método webViewDidFinishLoad, mas permite que você faça algo depois de ter sido chamado e não seja chamadas repetidas para esse método específico (por exemplo, mostrando um botão) também.

** * ** * *** EDIT * ** * ** * **

Eu fiz um teste e consegui testá-lo. ele realmente funciona e o método chamado a partir da notificação será chamado depois que a página inteira for carregada.

Como alternativa, acho que você pode fazer um contador no método delegado webViewDidStartLoad e também no webViewDidFinishLoad para garantir que eles sejam iguais antes de executar seus códigos. isso, porém, é um hack feio, pois nunca saberemos quantas vezes ele será chamado, a menos que, como eu, você esteja carregando um feed html e possa adicionar um JavaScript para verificar quantos elementos existem na página que você está carregando. Estou apenas compartilhando alguns dos methods que tentei resolver. espero que ajude.

feedback é encorajado. obrigado!

Aqui está o que eu uso para mostrar um spinner enquanto DOM carrega, construído em cima da resposta do @ Vinod.

Observe que entre webViewDidStartLoad e webViewDidFinishLoad o readyState é concluído a partir da solicitação anterior (se houver), é por isso que a pesquisa deve começar após webViewDidFinishLoad .

Os valores possíveis do readyState estão sendo carregados , interativos ou completos (e talvez nulos ?)

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

A maneira que eu faço é isto:

 - (void)webViewDidFinishLoad:(UIWebView *)webview { if (webview.loading) return; // now really done loading code goes next [logic] }