UIWebView shouldStartLoadWithRequest только один раз?
В моем приложении iPhone у меня есть UIWebView, где я загружаю локальный html. Все работает очень хорошо, но теперь я хочу иметь возможность обрабатывать локальные ссылки (в сносках): когда я нажимаю на локальную ссылку, я хочу иметь возможность перейти к сноске, на которую она ссылается, а затем вернуться,
<a href="#tofootnote">jump to footnote</a>
Я обработал это, добавив свой код в shouldStartLoadWithRequest и перехватив клики по локальной ссылке; при щелчке по локальной ссылке я работаю над своей магией (скрыть некоторые элементы ui, добавить кнопку "Назад" и т.д.); нажатие на кнопку "Назад" возвращает меня обратно в исходное местоположение в документе html.
Проблема заключается в том, что нажатие ONCE AGAIN по ссылке больше не вызывает shouldStartLoadWithRequest. I.e., следующий код:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSLog(@"foo bar");
return YES;
}
отображает только "foo bar" ONCE (фактически, дважды - первый раз, когда я первоначально загружаю документ), но только спустя один раз, независимо от того, сколько раз я нажимаю на локальную ссылку
Итак, если у кого-то нет лучшего объяснения, я предполагаю, что UIWebView кэширует документ или ссылку или что-то еще и больше не вызывает обработчик после первоначального вызова; Если это так, как я могу очистить этот внутренний кеш? (без перезагрузки документа)
Ответы
Ответ 1
Единственное решение, которое я нашел для этой проблемы, это строка-замените все якоря из
"#anchor" - то, что считается URL-адресом, например "| anchor". Таким образом, UIWebView будет считать это реальной ссылкой и попытаться выполнить запрос при нажатии. Это решение, очевидно, будет работать только в том случае, если вы сами обрабатываете все клики и, следовательно, можете интерпретировать измененные привязки. Я могу понять причину поведения UIWebView, но это довольно неприятно. Делегату действительно нужны сообщения для соответствия обработчикам onclick и т.д.
Ответ 2
Я могу обойти это, установив 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;
}
}
Ответ 3
Один трюк, который я нашел, когда я столкнулся с этой проблемой, используя встроенные изменения в jQuery, состоял в том, чтобы добавить случайное число в хэш. Таким образом, iOS, кажется, считает это новым запросом:
//set location hash to path
set: function( path ) {
path += "&" + Math.random();
location.hash = path;
},
Это должно работать, динамически устанавливая путь через событие onclick.
Ответ 4
Кажется, что это происходит и для меня, когда я использую onclick = "window.location.hash =...; return false;" вместо захвата щелчка.
Если я немного перейду немного или нажму на другой якорь, я снова смогу использовать ссылку.
Ответ 5
Если вы загружаете контент с помощью loadHTMLString, например:
[webView loadHTMLString:htmlString baseURL:[[NSBundle mainBundle] bundleURL]];
Тогда, похоже, достаточно просто перезагрузить html-строку. При нажатии на якорь (снова) вызовите ваш делегат.
Ответ 6
Вариант на бен-Долман (рабочий) код выше. Он "сбрасывает" кеш UIWebView с двумя фиктивными ссылками, чтобы последующие ссылки по-прежнему вызывали метод. Сначала он сохраняет внутреннюю ссылку или фрагмент в NSString с именем savedFragment. Затем он сообщает 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
}
}
Ответ 7
Попробуйте "прикоснуться" к тегу привязки (назначьте его самому). Моя гипотеза заключается в том, что это приведет к обновлению DOM, что снова проверит связь. Не проверял это, это просто идея!
Ответ 8
NSURLRequest * request = [NSURLRequest requestWithURL: fileURL cachePolocy: NSURLRequestReloadIgnoringLocalCacheData timeoutInterval: 60.0];
[webView loadRequest: request];