UIWebView долженStartLoadWithRequest вызываться только один раз? - PullRequest
16 голосов
/ 03 декабря 2009

В моем приложении для iPhone у меня есть UIWebView, где я загружаю локальный HTML. Все работает просто отлично, но теперь я хочу иметь возможность обрабатывать локальные ссылки (на сноски): когда я нажимаю на локальную ссылку, я хочу иметь возможность перейти к сноске, на которую она ссылается, а затем иметь возможность вернуться ,

<a href="#tofootnote">jump to footnote</a>

Я справился с этим, добавив свой код в shouldStartLoadWithRequest и перехватывая щелчки по локальной ссылке; когда щелкают по локальной ссылке, я работаю над своей магией (скрываю некоторые элементы пользовательского интерфейса, добавляю кнопку возврата и т. д.); Нажатие на кнопку «Назад» возвращает меня к исходному местоположению в HTML-документе.

Проблема в том, что нажатие ОДНАЖДЫ СНОВА на ссылку больше не вызывает метод mustStartLoadWithRequest. Т.е. следующий код:

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
 NSLog(@"foo bar");
 return YES;
}

отображает только «foo bar» ОДИН РАЗ (фактически, дважды - первый раз, когда я первоначально загружаю документ), но только ОДИН РАЗ после этого, независимо от того, сколько раз я нажимаю на локальную ссылку

Итак, если у кого-то нет лучшего объяснения, я предполагаю, что UIWebView кэширует документ, ссылку или что-то еще и больше не вызывает обработчик после первоначального вызова; Если это так, как я могу очистить этот внутренний кэш? (без перезагрузки документа)

Ответы [ 8 ]

14 голосов
/ 17 июля 2010

Единственное решение, которое я нашел для этой проблемы, - заменить все якоря из строки «#anchor» к чему-то, что считается URL, например «| anchor». Таким образом, UIWebView будет думать, что это настоящая ссылка, и будет пытаться выполнить запрос при нажатии. Это решение, очевидно, будет работать, только если вы обрабатываете все щелчки самостоятельно и, следовательно, можете интерпретировать измененные якоря. Я могу понять причину поведения UIWebView, но это довольно расстраивает. Делегат действительно нуждается в сообщениях, совпадающих с обработчиками onclick и т. Д.

6 голосов
/ 01 ноября 2012

Я могу обойти это, установив window.location в качестве фиктивного якоря после обработки действительного.

- (BOOL)webView:(UIWebView *)aWebView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
    if ([[request URL] fragment]) {
        if ([[[request URL] fragment] isEqualToString:@"__DUMMY_ANCHOR"])
            return NO;

        // Do your custom handling of the anchor here

        // Change the location to a non-existent anchor
        [aWebView stringByEvaluatingJavaScriptFromString:@"window.location='#__DUMMY_ANCHOR'"];

        return NO;
    }
}
1 голос
/ 21 июня 2012

Одна хитрость, которую я обнаружил, столкнувшись с этой проблемой, используя изменения, встроенные в jquery mobile, заключалась в добавлении случайного числа в хеш. Таким образом, iOS, кажется, думает, что это новый запрос:

//set location hash to path
set: function( path ) {
    path += "&" + Math.random();
    location.hash = path;
},

Это должно работать, динамически устанавливая путь и через событие onclick.

0 голосов
/ 23 января 2013

Вариант (рабочий) код Бена Долмана выше. Он «сбрасывает» кэш UIWebView с двумя фиктивными ссылками, чтобы последующие ссылки по-прежнему вызывали метод. Сначала он сохраняет внутреннюю ссылку или фрагмент в строке NSSt с именем saveFragment. Затем он сообщает UIWebview загрузить первую фиктивную ссылку #pageX, а затем еще одну #pageY. Наконец, он захватывает сохраненный фрагмент и использует его для создания номера страницы, который затем используется в отдельном методе для прокрутки UIWebview в правильное местоположение.

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {


   if ([[request URL] fragment]) { //check if fragment exists (treat as internal link)

       NSString *fragment = [[request URL] fragment];

       //If the fragment is neither "pageX" nor "pageY", treat as an internal link in the PDF
       if (![fragment isEqualToString:@"pageX"] &&
           ![fragment isEqualToString:@"pageY"]) {

           savedFragment = fragment; //hold the fragment in savedFragment (NSString)
           [pdfWebView stringByEvaluatingJavaScriptFromString:@"window.location='#pageX'"]; //load UIWebView with first dummy link

       } else if ([fragment isEqualToString:@"pageX"]) {

           [pdfWebView stringByEvaluatingJavaScriptFromString:@"window.location='#pageY'"]; //load UIWebView with second dummy link

       } else {

           NSString *pageString = [savedFragment stringByReplacingOccurrencesOfString:@"page" withString:@""]; //grab the page from savedFragment
           int page = [pageString intValue];
           [self scrollWebViewToPage:page-1]; //scroll to page (seperate method)
       }

       return NO; //do not load any of the dummy links

   } else {

       return YES; //first load of PDF into UIWebView should be allowed
   }

}
0 голосов
/ 14 июня 2011

Если вы загружаете контент с помощью loadHTMLString, например:

[webView loadHTMLString:htmlString baseURL:[[NSBundle mainBundle] bundleURL]];

Тогда, кажется, достаточно просто перезагрузить html-строку. Нажав на якорь, вы снова вызовете хук делегата.

0 голосов
/ 30 июня 2010

NSURLRequest * request = [NSURLRequest requestWithURL: fileURL cachePolocy: NSURLRequestReloadIgnoringLocalCacheData timeoutInterval: 60.0];

[webView loadRequest: запрос];

0 голосов
/ 16 февраля 2010

Это, кажется, происходит и для меня, когда я использую onclick = "window.location.hash = ...; return false;" вместо захвата клика.

Если немного прокрутить или щелкнуть другой якорь, я снова смогу воспользоваться ссылкой.

0 голосов
/ 20 января 2010

Попробуйте «прикоснуться» к тегу привязки (назначьте его себе). Моя гипотеза заключается в том, что DOM обновится, и он снова проверит ссылку. Не проверял это, это просто идея!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...