UIWebView - Как определить «последнее» сообщение webViewDidFinishLoad? - PullRequest
21 голосов
/ 26 мая 2009

Кажется, что сообщение webViewDidFinishLoad отправляется каждый раз, когда любой объект на странице был загружен. Есть ли способ определить, что вся загрузка контента выполнена?

Ответы [ 10 ]

60 голосов
/ 09 мая 2010

Я предполагаю, что iframes вызывают пару 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_--;
}

(Обратите внимание, что это будет работать только в том случае, если пары начало / конец не приходят последовательно, но, по моему опыту, пока этого не произошло.)

19 голосов
/ 23 апреля 2014

Отметьте этот пункт, он точно будет работать для вас:

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    if ([[webView stringByEvaluatingJavaScriptFromString:@"document.readyState"] isEqualToString:@"complete"]) {
        // UIWebView object has fully loaded.
    }
}
9 голосов
/ 26 мая 2009

Интересно, я бы не подумал, что так будет работать. Хотя я уверен, что есть другие способы сделать это (есть ли способ извлечь URL из сообщения webViewDidFinishLoad, чтобы вы могли видеть, какая из них является главной страницей, заканчивающей загрузку?), Главное, что я могу придумать, - это использовать предполагаемый прогресс, чтобы проверить прогресс страницы и запустить все, что вы хотите сделать, когда загрузка будет завершена на 100%, что я и делаю в своем приложении. Google "Iphone WebView оценивается прогресс" и нажмите первую ссылку для руководства, которое я написал о том, как это сделать.

Обновление:

Пожалуйста, используйте ответ Фопкинса ниже вместо моего! Использование частных API в ваших приложениях - плохая идея, и вы, вероятно, будете отвергнуты, и его решение является правильным.

1 голос
/ 14 февраля 2014

Все опции не работают для моего варианта использования. Я использовал пример слегка измененного Фопкинса. Я обнаружил, что если 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--;
}
1 голос
/ 30 января 2014

Мне нужно было захватить переменную со страницы, которая еще не была загружена полностью.

Это сработало для меня:

- (void) webViewDidFinishLoad:(UIWebView *)webView {
    NSString *valueID = [webView stringByEvaluatingJavaScriptFromString:@"document.valueID;"];

    if([valueID isEqualToString:@""]){
        [webView reload];
        return;
    }

    //page loaded
}
1 голос
/ 02 января 2013

Вы также можете использовать эту короткую категорию, которую я написал, которая добавляет блоки в UIWebView, а также позволяет выбирать между поведением UIWebView по умолчанию (получение уведомлений после каждой загрузки объекта) или «ожидаемым» поведением (получение уведомлений только после полной загрузки страницы загружен).

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

1 голос
/ 30 августа 2012

Другой способ отслеживать ход загрузки с меньшим контролем - это наблюдать за уведомлениями WebViewProgressEstimateChangedNotification, WebViewProgressFinishedNotification и WebViewProgressStartedNotification. Например, вы могли наблюдать эти уведомления, чтобы реализовать простой индикатор прогресса в вашем приложении. Вы обновляете индикатор прогресса, вызывая методtimateProgress, чтобы получить оценку количества загруженного контента.

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

0 голосов
/ 15 марта 2016

Вот то, что я использую, чтобы показать спиннер во время загрузки DOM, построенный поверх ответа @ Vinod.

Обратите внимание, что между webViewDidStartLoad и webViewDidFinishLoad readyState равно завершено из предыдущего запроса (если есть), поэтому опрос должен начинаться после webViewDidFinishLoad.

readyState возможными значениями являются загрузка , интерактивная или завершение (а может быть ноль ?)

- (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];
}
0 голосов
/ 09 мая 2012

Привет, это может быть уже далеко, но я надеюсь, что это помогает.

Я просто использовал уведомление, когда оно входит в метод webViewDidFinishLoad, чтобы я мог перехватить один экземпляр метода, а затем я обнаружу уведомление и оттуда сделаю свою логику.

надеюсь, это поможет. он не захватывает последний вызванный экземпляр метода webViewDidFinishLoad, но позволяет вам делать что-то после его вызова и не повторять вызовы этого конкретного метода (например, показ кнопки).

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

Я сделал тест и смог его проверить. это на самом деле работает, и метод, вызываемый из уведомления, будет вызван после полной загрузки страницы.

в качестве альтернативы, я думаю, вы можете сделать счетчик для метода делегата webViewDidStartLoad, а также для webViewDidFinishLoad, чтобы убедиться, что они совпадают, прежде чем запускать ваши коды. это, однако, ужасный хак, поскольку мы никогда не узнаем, сколько раз он будет вызываться, если только я, как и вы, не загружаете html-фид и можете добавить JavaScript, чтобы проверить, сколько элементов на странице, которую вы загружаете. Я просто делюсь некоторыми методами, которые я пытался решить. надеюсь, это поможет.

обратная связь приветствуется. спасибо!

0 голосов
/ 21 июня 2009

То, как я это делаю, таково:

- (void)webViewDidFinishLoad:(UIWebView *)webview  {
    if (webview.loading)
    return;
    // now really done loading code goes next
    [logic]
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...