【问题标题】:UIWebView shouldStartLoadWithRequest only called once?UIWebView shouldStartLoadWithRequest 只调用一次?
【发布时间】:2009-12-03 14:48:35
【问题描述】:

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

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

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

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

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

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

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

【问题讨论】:

  • 附言。我正在使用 loadHTMLString 加载 UIWebView(因为我需要设置 baseURL),所以我无法为原始加载请求设置缓存策略。
  • 实际上,即使使用 urlrequest 和缓存策略仍然不起作用。请帮帮我!

标签: iphone html uiwebview


【解决方案1】:

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

【讨论】:

  • 你说你能理解原因。你可以解释吗?我根本无法理解原因,就我而言,这是 UIWebView 中的一个错误。无论代理是否被调用,webview 都应该在任何时候被点击导航到指定的链接,而不仅仅是一次。
  • 原因很简单。从技术上讲,目前存在的 UIWebView 回调是用于处理点击网页的“检索”。当您单击哈希链接时,您不会检索页面,而只会在当前页面中导航。因此从技术上讲,这不是一个错误。除非你认为糟糕的 API 设计是一个错误。我倾向于认为糟糕的设计是一个错误.. 但我承认苹果可能有不同的看法;-)
【解决方案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】:

          上面 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
             }
          
          }
          

          【讨论】:

            【解决方案7】:

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

            【讨论】:

            • 我现在遇到了完全相同的问题。我尝试了您的解决方案,但没有帮助。
            【解决方案8】:

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

            [webView loadRequest:request];

            【讨论】:

            • 我现在遇到了完全相同的问题。我证明更改缓存策略选项不起作用。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-01-21
            • 2013-07-11
            • 2013-09-13
            • 2012-01-10
            相关资源
            最近更新 更多