2009-12-03 4 views
16

Dans mon application iPhone, j'ai un UIWebView sur lequel je charge un code html local. Tout fonctionne très bien, mais maintenant je veux être capable de gérer les liens locaux (aux notes de bas de page): quand je clique sur un lien local, je veux pouvoir passer à la note de bas de page référencée, puis pouvoir revenir .UIWebView shouldStartLoadWithRequest seulement appelé une fois?

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

Je me suis occupé en ajoutant mon code pour intercepter et shouldStartLoadWithRequest clics sur les liens locaux; quand on clique sur un lien local, je travaille ma magie (cache des éléments d'interface utilisateur, ajoute un bouton de retour, etc.); cliquer sur le bouton retour me ramène à l'emplacement d'origine dans le document html.

Le problème est que cliquer une fois de plus sur le lien n'appelle plus shouldStartLoadWithRequest. À savoir, le code suivant:

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

n'affiche « foo bar » UNE FOIS (en fait, à deux reprises - la première fois que je charge d'abord le document), mais seulement une fois par la suite, peu importe combien de fois je m en cliquant sur le lien local

Donc, à moins que quelqu'un n'ait une meilleure explication, je devine que UIWebView met en cache le document ou le lien ou quelque chose et n'appelle plus le gestionnaire après l'appel initial; Si c'est le cas, comment puis-je effacer ce cache interne? (sans recharger le document)

+0

PS. Je charge l'UIWebView en utilisant loadHTMLString (car j'ai besoin de configurer l'URL de base), donc je ne peux pas configurer la politique de cache pour la demande de chargement d'origine. – Alex

+0

En fait, même l'utilisation de la requête urlrequest et de la politique de cache ne fonctionne toujours pas. Aidez-moi, s'il vous plaît! – Alex

Répondre

14

La seule solution que j'ai trouvée pour ce problème est de remplacer toutes les ancres de "#anchor" par quelque chose qui est considéré comme une URL, comme "| anchor". De cette façon, UIWebView pensera que c'est un vrai lien et tentera la requête quand on cliquera dessus. Cette solution ne fonctionnera évidemment que si vous manipulez vous-même tous les clics et pouvez donc interpréter les ancres modifiées. Je peux comprendre la raison du comportement d'UIWebView, mais c'est plutôt frustrant. Le délégué a vraiment besoin de messages pour correspondre aux gestionnaires onclick, etc.

+0

Merci cette solution a travaillé pour moi aussi – Dilshan

+0

Vous dites que vous pouvez comprendre la raison. Peux-tu expliquer? Je ne peux pas comprendre la raison du tout et en ce qui me concerne c'est un bug dans UIWebView. Que le délégué soit appelé ou non, le webview doit naviguer vers le lien spécifié chaque fois qu'il est cliqué, pas seulement une fois. – kball

+2

La raison est simple. Techniquement, les rappels UIWebView qui existent actuellement sont pour gérer la "récupération" des pages Web cliquées. Lorsque vous cliquez sur un lien de hachage, vous ne récupérez pas une page, naviguez uniquement dans la page en cours. Donc, techniquement, ce n'est pas un bug. Sauf si vous considérez que la conception de l'API est mauvaise. J'ai tendance à penser que la mauvaise conception est un bug .. mais je concède que Apple pourrait avoir une opinion différente ;-) – GrafikRobot

-1

Essayez de 'toucher' le point d'ancrage (attribuez-le à lui-même). Mon hypothèse est que cela provoquera la mise à jour du DOM, le faisant vérifier à nouveau le lien. N'a pas testé cela, c'est juste une idée!

+0

J'ai exactement le même problème en ce moment .. J'ai essayé votre solution, et cela n'aide pas. – GrafikRobot

0

Cela semble se produire pour moi aussi quand j'utilise un onclick = "window.location.hash = ...; return false;" au lieu de capturer le clic.

Si je fais défiler un peu ou que je clique sur une autre ancre, je peux à nouveau utiliser le lien.

-1

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

[webView loadRequest: request];

+0

J'ai exactement le même problème pour le moment. Et j'atteste que changer l'option de politique de cache ne fonctionne pas. – GrafikRobot

0

Si vous êtes en train de charger le contenu en utilisant l'loadHTMLString, comme:

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

il semblerait donc être suffisant juste pour recharger la chaîne html. En cliquant sur l'ancre, vous appelez (de nouveau) votre point d'accès délégué.

1

Une astuce que j'ai trouvée en rencontrant ce problème en utilisant les changements de pages embarqués jquery mobile était d'ajouter un nombre aléatoire sur le hachage. De cette façon, iOS semble que ce soit une nouvelle demande:

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

Cela devrait fonctionner en réglant dynamiquement le chemin à travers un événement onclick aussi bien.

6

Je suis en mesure de contourner ce problème en définissant window.location à une ancre factice après avoir manipulé le valide.

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

Une variation du code de Ben Dolman (fonctionnant) ci-dessus. Il "réinitialise" le cache UIWebView avec les deux liens fictifs afin que les liens suivants appellent toujours la méthode. D'abord, il enregistre le lien interne, ou fragment dans un NSString appelé savedFragment. Il indique ensuite à UIWebview de charger le premier lien factice #pageX puis un autre #pageY. Enfin, il saisit savedFragment et l'utilise pour construire le numéro de page, qui est ensuite utilisé dans une méthode séparée pour faire défiler UIWebview vers l'emplacement correct.

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

} 
Questions connexes