2009-12-03 7 views
16

In meiner iPhone App habe ich ein UIWebView, in dem ich einen lokalen HTML-Code lade. Alles funktioniert gut, aber jetzt möchte ich mit lokalen Links (zu Fußnoten) umgehen können: Wenn ich auf einen lokalen Link klicke, möchte ich in die Fußnote springen können und dann zurückkommen können .UIWebView shouldStartLoadWithRequest nur einmal aufgerufen?

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

ich behandelt dies durch meinen Code should Hinzufügen und lokalen Link klickt abfangen; wenn ein lokaler Link angeklickt wird, arbeite ich meine Magie (verstecken Sie einige ui-Elemente, fügen Sie einen Zurück-Button, etc ..); Ein Klick auf den Zurück-Button bringt mich zurück zum ursprünglichen Ort im HTML-Dokument.

Das Problem besteht darin, dass das Klicken auf ONCE AGAIN auf der Verknüpfung nicht mehr ruft, sollte StartLoadWithRequest. Das heißt, der folgende Code:

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

zeigt nur „foo bar“ ONCE (eigentlich zweimal - das erste Mal, wenn ich zunächst das Dokument laden), aber nur einmal danach, und zwar unabhängig davon, wie oft ich Klicken Sie auf den lokalen Link

Also, es sei denn, jemand hat eine bessere Erklärung, ich vermute, dass die UIWebView das Dokument oder Link oder etwas zwischenspeichert und nicht mehr den Handler nach dem ersten Aufruf anruft; Wenn dies der Fall ist, wie kann ich diesen internen Cache löschen? (ohne das Dokument erneut zu laden)

+0

PS. Ich lade die UIWebView mit loadHTMLString (weil ich die baseURL einrichten muss), so dass ich die Cache-Richtlinie für die ursprüngliche Ladeanforderung nicht einrichten kann. – Alex

+0

Eigentlich funktioniert auch die Verwendung von URL-Anfrage und Cache-Politik immer noch nicht. Hilf mir bitte! – Alex

Antwort

14

Die einzige Lösung, die ich für dieses Problem gefunden habe, ist String-ersetzen alle Anker von "#Anchor" zu etwas, das als URL, wie "| Anker" betrachtet wird. Auf diese Weise wird UIWebView glauben, dass es sich um einen echten Link handelt, und die Anfrage versuchen, wenn darauf geklickt wird. Diese Lösung funktioniert natürlich nur, wenn Sie alle Klicks selbst bearbeiten und somit die geänderten Anker interpretieren können. Ich kann den Grund für das Verhalten von UIWebView verstehen, aber es ist ziemlich frustrierend. Der Delegat benötigt wirklich Nachrichten, die den Onclick-Handlern entsprechen.

+0

Danke diese Lösung funktionierte für mich auch – Dilshan

+0

Sie sagen, dass Sie den Grund verstehen können. Können Sie erklären? Ich kann den Grund überhaupt nicht verstehen und soweit es mich betrifft, ist dies ein Fehler in UIWebView. Unabhängig davon, ob der Delegat aufgerufen wird oder nicht, sollte die Webansicht nicht nur einmal auf den angegebenen Link klicken, wenn sie angeklickt wird. – kball

+2

Der Grund ist einfach. Technisch gesehen sind die UIWebView Callbacks, die derzeit existieren, um den "Abruf" der angeklickten Webseiten zu handhaben. Wenn Sie auf einen Hash-Link klicken, rufen Sie keine Seite ab und navigieren nur auf der aktuellen Seite. Daher ist es technisch gesehen kein Fehler. Es sei denn, Sie halten ein schlechtes API-Design für einen Fehler. Ich neige dazu zu denken, schlechtes Design ist ein Bug .. aber ich gestehe, Apple könnte eine andere Meinung haben ;-) – GrafikRobot

-1

Versuchen Sie, das Anker-Tag zu berühren (weisen Sie es sich zu). Meine Hypothese ist, dass das DOM aktualisiert wird, so dass es den Link erneut überprüft. Habe das nicht getestet, es ist nur eine Idee!

+0

Ich habe genau das gleiche Problem im Moment .. Ich habe Ihre Lösung versucht, und es hilft nicht. – GrafikRobot

0

Dies scheint auch für mich passiert, wenn ich ein onclick verwenden = "window.location.hash = ...; return false;" anstatt den Klick zu erfassen.

Wenn ich ein wenig rolle oder auf einen anderen Anker klicke, kann ich den Link erneut verwenden.

-1

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

[webView loadRequest: Anfrage];

+0

Ich habe genau das gleiche Problem im Moment .. Und ich bestätige, dass das Ändern der Cache-Richtlinien-Option nicht funktioniert. – GrafikRobot

0

Wenn Ihr den Inhalt Laden der loadHTMLString verwenden, wie:

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

Dann scheint es ausreichend zu sein, nur die HTML-Zeichenfolge erneut zu laden. Wenn Sie auf den Anker klicken, wird (erneut) Ihr Delegate-Hook aufgerufen.

1

Ein Trick, den ich gefunden habe, als ich dieses Problem mit jQuery Mobile Embedded Page Changes auftrat, war das Hinzufügen einer Zufallszahl in den Hash. Auf diese Weise iOS scheint zu glauben, es ist eine neue Anfrage:

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

Dies auch durch die dynamische Einstellung des Pfades durch ein Onclick-Ereignis funktionieren soll.

6

Ich bin in der Lage, dies zu umgehen, indem Sie window.location zu einem Dummy-Anker nach der Handhabung der gültigen.

- (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; 
    } 
} 
0

Eine Variation von Ben Dolmans (Arbeits) Code oben. Es "setzt" den UIWebView-Cache mit den beiden Dummy-Links zurück, so dass nachfolgende Links die Methode noch aufrufen. Zuerst speichert es die interne Verknüpfung oder das Fragment in einem NSString namens savedFragment. Dann teilt es dem UIWebview mit, dass er den ersten Dummy-Link #pageX und dann ein anderes #pageY laden soll. Schließlich wird die savedFragment-Datei abgerufen und verwendet, um die Seitennummer zu erstellen, die dann in einer separaten Methode verwendet wird, um den UIWebview zum richtigen Speicherort zu scrollen.

- (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 
    } 

}