2009-12-03 20 views
16

Nella mia app per iPhone, ho un UIWebView in cui sto caricando un html locale. Tutto funziona alla perfezione, ma ora voglio essere in grado di gestire i collegamenti locali (a note): quando clicco su un link locale, voglio essere in grado di saltare alla nota a cui fa riferimento, quindi essere in grado di tornare indietro .UIWebView dovrebbeStartLoadWithRequest chiamato solo una volta?

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

ho gestito questo aggiungendo il mio codice di shouldStartLoadWithRequest e intercettare i clic sui link locali; quando si fa clic su un collegamento locale, lavoro la mia magia (nascondi alcuni elementi dell'interfaccia utente, aggiungi un pulsante indietro, ecc.); cliccando sul pulsante indietro mi riporta alla posizione originale nel documento html.

Il problema è che se si fa clic di NUOVO ANCORA sul link non si effettuano più chiamate shouldStartLoadWithRequest. Vale a dire, il seguente codice:

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

visualizza solo "foo bar" ONCE (in realtà, due volte - la prima volta quando sto inizialmente il caricamento del documento), ma solo una volta dopo, indipendentemente da quante volte ho' m clic sul collegamento locale

Quindi, a meno che qualcuno non abbia una spiegazione migliore, suppongo che UIWebView memorizzi nella cache il documento o il collegamento o qualcosa e non chiami più il gestore dopo la chiamata iniziale; Se questo è il caso, come posso cancellare questa cache interna? (senza ricaricare il documento)

+0

PS. Sto caricando UIWebView usando loadHTMLString (perché ho bisogno di impostare il baseURL), quindi non posso impostare il criterio di cache per la richiesta di caricamento originale. – Alex

+0

In realtà, anche l'uso di urlrequest e della cache non funziona ancora. Aiutami per favore! – Alex

risposta

14

L'unica soluzione che ho trovato per questo problema è di sostituire le stringhe di tutti gli ancoraggi da "#anchor" a qualcosa che è considerato un URL, come "| ancora". In questo modo UIWebView penserà che sia un vero collegamento e tenterà la richiesta quando cliccato. Questa soluzione funzionerà ovviamente solo se si gestiscono tutti i clic da soli e quindi è possibile interpretare le ancore modificate. Riesco a capire il motivo del comportamento di UIWebView, ma è piuttosto frustrante. Il delegato ha davvero bisogno di messaggi per abbinare i gestori onclick, ecc.

+0

Grazie anche a questa soluzione ha funzionato anche per me – Dilshan

+0

Tu dici di poter capire il motivo. Puoi spiegare? Non riesco a capire il motivo e per quanto mi riguarda questo è un bug in UIWebView. Indipendentemente dal fatto che il delegato venga chiamato o meno, la webview dovrebbe navigare sul link specificato ogni volta che viene cliccato, non solo una volta. – kball

+2

Il motivo è semplice. Tecnicamente i callback di UIWebView attualmente esistenti sono per la gestione del "recupero" delle pagine Web cliccate. Quando fai un clic su un collegamento hash non stai recuperando una pagina, navigando solo nella pagina corrente. Quindi tecnicamente non è un bug. A meno che tu non consideri il cattivo design delle API come un bug. Tendo a pensare che il cattivo design sia un bug .. ma concedo che Apple potrebbe avere un'opinione diversa ;-) – GrafikRobot

-1

Provare a "toccare" il tag di ancoraggio (assegnarlo a se stesso). La mia ipotesi è che farà sì che il DOM si aggiorni, facendo di nuovo controllare il link. Non ho provato questo, è solo un'idea!

+0

Al momento sto avendo lo stesso identico problema. Ho provato la tua soluzione, e non aiuta. – GrafikRobot

0

Questo sembra accadere anche per me quando uso un onclick = "window.location.hash = ...; restituisce false;" invece di catturare il clic.

Se faccio scorrere un po 'o clicco su un'altra ancora, posso usare di nuovo il collegamento.

-1

NSURLRequest * request = [NSURLRequest requestWithURL: fileURL cachePolocy: NSURLRequestReloadIgnoringLocalCacheData timeoutInterval: 60,0];

[webView loadRequest: richiesta];

+0

Al momento sto avendo lo stesso identico problema. E attesto che la modifica dell'opzione relativa alla politica della cache non funziona. – GrafikRobot

0

Se stai caricando il contenuto utilizzando il loadHTMLString, come:

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

Poi sembra essere sufficiente solo per ricaricare il HTML-stringa. Facendo clic sull'ancora, quindi (di nuovo) chiama il tuo hook delegato.

1

Un trucco che ho trovato quando mi sono imbattuto in questo problema utilizzando le modifiche alle pagine incorporate di jquery mobile era di aggiungere un numero casuale all'hash. In questo modo iOS sembra pensare che sia una nuova richiesta:

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

Questo dovrebbe funzionare impostando dinamicamente il percorso attraverso un evento onclick pure.

6

Sono in grado di risolvere il problema impostando window.location su un'ancora fittizia dopo aver gestito quello valido.

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

Una variazione sul codice (funzionante) di Ben Dolman in alto. "Reimposta" la cache di UIWebView con i due collegamenti fittizi in modo che i collegamenti successivi continuino a chiamare il metodo. Per prima cosa salva il collegamento interno, o frammento in un NSString chiamato SavedFragment. Quindi dice a UIWebview di caricare il primo link fittizio #pageX e poi un altro #pageY. Alla fine prende il Frammento salvato e lo usa per costruire il numero di pagina, che viene poi usato in un metodo separato per far scorrere UIWebview nella posizione corretta.

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

} 
Problemi correlati