web-dev-qa-db-ja.com

UIWebView didFinishLoadingが複数回起動します

UIWebViewがドキュメントの読み込みを完了した後に実行する必要のあるコードがあります。そのために、UIWebViewのデリゲートをコントローラーに設定し、webViewDidFinishLoadingメソッドを実装しました。

ロードするページのタイプに応じて、これは複数回呼び出されます。それがajaxリクエスト、画像のリクエスト、またはiframeのリクエストなのかどうかはわかりません。

メインリクエストが終了したこと、つまりHTMLが完全にロードされたことを通知する方法はありますか?

または、これらのイベントのすべてが実行を完了するまで、コードの実行を遅らせますか?

52
Ben Scheirman

NSLogがロードの開始と終了のトレースを記録することは(まだここまで行っていないのであれば)啓発的かもしれません。

    - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
       NSLog(@"Loading: %@", [request URL]);
       return YES;
    }


    - (void)webViewDidFinishLoad:(UIWebView *)webView {
       NSLog(@"didFinish: %@; stillLoading: %@", [[webView request]URL],
            (webView.loading?@"YES":@"NO"));
    }


    - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
       NSLog(@"didFail: %@; stillLoading: %@", [[webView request]URL],
            (webView.loading?@"YES":@"NO"));
    }

バンドルからヘルプページをロードし、埋め込みリソース(外部css、YUI !、画像)を含むプロジェクトの1つで、3つすべての呼び出しを見ました。通過する唯一のリクエストは、最初のページのロードであり、shouldStartLoadWithRequestはどの依存関係に対しても呼び出されません。したがって、didFinishLoadが複数回呼び出されるのはなぜか不思議です。

おそらく、表示されているのはリダイレクトによるものか、前述のように、ロードされたページ内のajax呼び出しによるものです。ただし、少なくともshouldStartLoadと他の2つのデリゲート関数の呼び出しのバランスを取り、ロードがいつ終了するかを判断できる必要があります。

48
wkw

ロードが終了したときに確認するには、このようなことを行うことができます。同じページに多くのコンテンツを配置できるため、必要です。

- (void)webViewDidFinishLoad:(UIWebView *)webview  {
    if (webview.isLoading)
        return;
    // do some work
}
50
Scott Densmore

これをチェックして、あまりにも多くのコードを書く必要がないようにするための簡単で簡単な方法:

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

この質問はすでに解決されていますが、webViewDidFinishLoadへの複数の呼び出しが実際に予期される動作である理由を実際に説明する答えがありません

前述のメソッドは、webviewがフレームの読み込みを完了するたびに呼び出されます。 IWebViewDelegate protocol documentation から:

webViewDidFinishLoad:
Webビューがフレームの読み込みを完了した後に送信されます。

実際、これはUIWebViewDelegateプロトコルを構成する他のすべてのメソッドにも当てはまります。

8
Cezar

これを試してみてください

 -(void)webViewDidFinishLoad:(UIWebView *)webview  
    {
       if (webview.isLoading)
           return;
       else
       {
           // Use the code here which ever you need to run after webview loaded 
       }
    }
7
Yogeesh H T

これは、フレームの読み込みが完了するたびにコールバックメソッドが呼び出されるために発生します。これを防ぐには、webviewの「suppressesIncrementalRendering」プロパティをtrueに設定します。これにより、データ全体がメモリにロードされるまでWebViewがレンダリングされなくなります。これは私のためにトリックをしました

私は似たようなことに気づき、それは混乱でした:UITabBarControllerがあり、アプリケーションの起動時にタブにリンクされているすべてのViewControllersをプリロードしているようです(first_Tab_ViewControllerだけを表示しているにもかかわらず)複数のタブにViewControllerがWebViewとともにある場合、それぞれのwebViewDidFinishLoadが呼び出され、貼り付けた場合:

NSLog(@"size width %0.0f height %0.0f", fitingSize.width, fittingSize.height); 

いくつかの場合、2つの異なるUIWebViewsで実際にシングル呼び出しを行っているときに、ダブル呼び出しのように見えるコンソールでいくつかの出力を取得します。

2
Luis

WebViewDidFinishLoadメソッドで読み込みとリクエストのプロパティを確認できます

1
nico