Кажется, что сообщение webViewDidFinishLoad отправляется каждый раз при загрузке любого объекта на странице. Есть ли способ определить, что вся загрузка контента выполнена?
UIWebView — как определить последнее сообщение webViewDidFinishLoad?
Ответы (10)
Интересно, не думал, что так получится. Хотя я уверен, что есть и другие способы сделать это (есть ли способ извлечь URL-адрес из сообщения webViewDidFinishLoad, чтобы вы могли видеть, какая из них завершает загрузку главной страницы?), главное, что я могу придумать, это использовать предполагаемый прогресс, чтобы проверить ход страницы и запустить все, что вы хотите сделать, когда она на 100% завершит загрузку, что я и делаю в своем приложении. Погуглите «iphone webview Assessmentprogress» и нажмите на первую ссылку, чтобы найти руководство, которое я написал о том, как это сделать.
Обновлять:
Пожалуйста, используйте ответ Фопкинса ниже вместо моего! Использование частных API в ваших приложениях — плохая идея, и вы, вероятно, получите отказ, а его решение — правильное.
Я предполагаю, что 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_--;
}
(Обратите внимание, что это будет работать только в том случае, если пары «начало/конец» не приходят последовательно, но по моему опыту этого не произошло.)
(void)webView:(UIWebView*)webView didFailLoadWithError:(NSError*)error { -- webViewLoads_; }
- person ; 05.04.2011
Проверьте это, это определенно сработает для вас:
- (void)webViewDidFinishLoad:(UIWebView *)webView {
if ([[webView stringByEvaluatingJavaScriptFromString:@"document.readyState"] isEqualToString:@"complete"]) {
// UIWebView object has fully loaded.
}
}
Другой способ отслеживать ход загрузки с меньшим контролем — наблюдать за уведомлениями WebViewProgressEstimateChangedNotification, WebViewProgressFinishedNotification и WebViewProgressStartedNotification. Например, вы можете наблюдать за этими уведомлениями, чтобы реализовать в своем приложении простой индикатор хода выполнения. Вы обновляете индикатор выполнения, вызывая метод AssessmentProgress, чтобы получить оценку объема загруженного в данный момент контента.
Вы также можете использовать эту короткую категорию, которую я написал, которая добавляет блоки в UIWebView, а также позволяет вам выбирать между поведением UIWebView по умолчанию (получение уведомления после загрузки каждого объекта) или «ожидаемым» поведением (получение уведомления только тогда, когда страница полностью загружена).
https://github.com/freak4pc/UIWebView-Blocks
Мне нужно было захватить переменную со страницы, которая еще не была полностью загружена.
Это сработало для меня:
- (void) webViewDidFinishLoad:(UIWebView *)webView {
NSString *valueID = [webView stringByEvaluatingJavaScriptFromString:@"document.valueID;"];
if([valueID isEqualToString:@""]){
[webView reload];
return;
}
//page loaded
}
Все варианты действительно не работали для моего варианта использования. Я использовал слегка измененный пример Phopkins. Я обнаружил, что если 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--;
}
привет это может быть уже немного далеко назад, но я надеюсь, что это поможет.
я просто использовал уведомление, когда оно входит в метод webViewDidFinishLoad, чтобы я мог захватить один экземпляр метода, а затем обнаружу уведомление и оттуда выполню свою логику.
надеюсь это поможет. он не захватывает последний вызванный экземпляр метода webViewDidFinishLoad, но позволяет вам делать что-то после его вызова и не повторять вызовы этого конкретного метода (например, показ кнопки).
*********ИЗМЕНИТЬ********
я сделал тест и удалось проверить его. это действительно работает, и метод, вызываемый из уведомления, будет вызываться после загрузки всей страницы.
в качестве альтернативы, я думаю, вы можете сделать счетчик для метода делегата webViewDidStartLoad, а также для webViewDidFinishLoad, чтобы убедиться, что они одинаковы, прежде чем запускать свои коды. это, тем не менее, уродливый хак, поскольку мы никогда не узнаем, сколько раз он будет вызываться, если, как и я, вы не загружаете html-канал и не можете добавить JavaScript, чтобы проверить, сколько элементов есть на странице, которую вы загружаете. я просто делюсь некоторыми методами, которые я пытался решить. Надеюсь, поможет.
обратная связь приветствуется. Благодарность!
webViewDidFinishLoad и созданием уведомления в webViewDidFinishLoad для вызова другого метода?
- person Aaron Brager; 08.03.2013
Вот что я использую, чтобы показать счетчик во время загрузки DOM, построенный на основе ответа @Vinod.
Обратите внимание, что между webViewDidStartLoad и webViewDidFinishLoad состояние readyState завершено из предыдущего запроса (если он был), поэтому опрос должен начаться после webViewDidFinishLoad.
Возможные значения readyState: loading, interactive или completed (а может быть, 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];
}
Я делаю это следующим образом:
- (void)webViewDidFinishLoad:(UIWebView *)webview {
if (webview.loading)
return;
// now really done loading code goes next
[logic]
}