UIWebView shouldStartLoadWithRequest只调用一次?

时间:2009-12-03 14:48:35

标签: iphone html uiwebview

在我的iPhone应用程序中,我有一个UIWebView,我正在加载一个本地的HTML。一切正常,但现在我想能够处理本地链接(到脚注):当我点击本地链接时,我希望能够跳到它所引用的脚注,然后能够回来。

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

我通过将我的代码添加到shouldStartLoadWithRequest并拦截本地链接点击来处理此问题;当点击本地链接时,我会运用我的魔法(隐藏一些ui元素,添加后退按钮等等);单击后退按钮会将我跳回到html文档中的原始位置。

问题是单击链接上的ONCE不再调用shouldStartLoadWithRequest。即,以下代码:

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

仅显示“foo bar”ONCE(实际上,两次 - 我第一次加载文档时),但之后只有ONCE,无论我点击本地链接多少次

所以,除非有人有更好的解释,否则我猜测UIWebView会缓存文档或链接或其他内容,并且在初始调用后不再调用处理程序;如果是这种情况,我该如何清除此内部缓存? (不重新加载文件)

8 个答案:

答案 0 :(得分:14)

我发现这个问题的唯一解决方案是从字符串替换所有锚点 “#anchor”指向被视为URL的内容,例如“| anchor”。这样UIWebView就会认为它是一个真正的链接,并在点击时尝试该请求。这个解决方案显然只有在您自己处理所有点击时才有效,因此可以解释更改后的锚点。我可以理解UIWebView行为的原因,但它相当令人沮丧。委托真的需要消息来匹配onclick等处理程序。

答案 1 :(得分:6)

我可以通过在处理有效的锚点后将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;
    }
}

答案 2 :(得分:1)

当我使用jquery移动嵌入式页面更改遇到此问题时,我发现的一个技巧是在哈希上添加一个随机数。这样iOS似乎认为这是一个新的请求:

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

这应该通过动态设置onclick事件的路径来实现。

答案 3 :(得分:0)

当我使用onclick =“window.location.hash = ...; return false;”时,这似乎也发生在我身上。而不是捕获点击。

如果我稍微滚动或点击另一个锚点,我可以再次使用该链接。

答案 4 :(得分:0)

如果您使用loadHTMLString加载内容,例如:

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

然后重新加载html-string似乎就足够了。然后单击锚点将(再次)调用您的委托挂钩。

答案 5 :(得分:0)

上述Ben Dolman(工作)代码的变体。它使用两个虚拟链接“重置”UIWebView缓存,以便后续链接仍然可以调用该方法。首先,它将内部链接或片段保存在名为savedFragment的NSString中。然后它告诉UIWebview加载第一个虚拟链接#pageX然后另一个#pageY。最后,它抓取savedFragment并使用它来构造页码,然后在单独的方法中将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
   }

}

答案 6 :(得分:-1)

尝试'触摸'锚标记(将其分配给自身)。我的假设是会导致DOM更新,使其再次检查链接。没有测试过,这只是一个想法!

答案 7 :(得分:-1)

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

[webView loadRequest:request];