2010-05-29 10 views
8

Sto cercando di passare più cose da una pagina Web all'interno di una UIWebView indietro alla mia app iPhone tramite il metodo shouldStartLoadWithRequest di UIWebView.Triggering dovrebbeStartLoadWithRequest con più chiamate window.location.href

Fondamentalmente la mia pagina Web chiama window.location.href = "comando: // foo = bar" e sono in grado di intercettare quello nella mia app senza problemi. Ora, se creo un ciclo e faccio più chiamate window.location.href in una volta, quindi dovrebbe startStartLoadWithRequest sembra essere chiamato una sola volta e la chiamata che ottiene è l'ultimo sparo di window.location.href alla fine del ciclo.

La stessa cosa accade con la webview per Android, solo l'ultima window.location.href viene elaborata.

+0

Ho trovato una soluzione intelligente. Crea dinamicamente un iframe per ogni comando e imposta il suo src su "command: // foo = bar", puoi attivarlo più volte in un ciclo e dovresti chiamareStartLoadWithRequest ogni volta! Ora per studiare come ottimizzare questo. Non penso che sarebbe bello creare migliaia di iframe (anche se sono nascosti). Qualche suggerimento su questo? – AlBeebe

+0

Proverei anche a ottimizzare ogni chiamata di posizione. Se puoi inviare solo 60 chiamate al minuto, assicurati di interrompere tutte le chiamate con un numero sufficiente di query vars e frammenti per gestire più comandi per chiamata. Inoltre, potresti voler controllare wkWebView: http://nshipster.com/wkwebkit/ automatizza gran parte di questo processo ed è più affidabile. – newshorts

risposta

39
iFrame = document.createElement("IFRAME"); 
iFrame.setAttribute("src", "command://foo=bar"); 
document.body.appendChild(iFrame); 
iFrame.parentNode.removeChild(iFrame); 
iFrame = null; 

Quindi questo crea un iframe, imposta la sua origine a un im comando cercando di passare per l'applicazione, poi, non appena il suo aggiunto al corpo shouldStartLoadWithRequest viene chiamato, quindi togliamo l'iframe dal corpo, e impostarlo su null per liberare la memoria.

Ho anche provato questo su una webview Android utilizzando shouldOverrideUrlLoading e ha funzionato anche correttamente!

+3

Questa soluzione è orribilmente brutta, ma sembra essere la soluzione meno orribilmente brutta possibile. Sembra che Javascript "ottimizzi" ignorando le chiamate a window.location che vengono successivamente sostituite da altre chiamate a window.location. Grazie per avermi salvato da una sessione di debug molto dolorosa! – Arkaaito

+0

@Arkaaito +1 per l'orribile brutto, sono totalmente d'accordo – AlBeebe

+4

Voglio seguire da quando ho postato questo 2 anni fa. Ho scritto un'app per Android e iPhone che era fondamentalmente una webview racchiusa in un'app nativa. Ho usato questa soluzione così ho potuto comunicare dalla webview all'app nativa e ha funzionato perfettamente negli ultimi 2 anni ho avuto più di 500k + download della mia app. – AlBeebe

0

No, la modifica dell'URL dell'iframe non si innescherà shouldOverrideUrlLoading, almeno non in Android 2.2.

3

Ho colpito anche questo problema e qui è la mia soluzione che funziona per me. Tutte le mie funzioni JavaScript utilizzano questa funzione __js2oc (msg) per passare i dati e gli eventi a Objective-C tramite shouldStartLoadWithRequest: P.S. sostituisci "comando:" con il trigger "appname:" che usi.

/* iPhone JS2Objective-C bridge interface */ 
var __js2oc_wait = 300; // min delay between calls in milliseconds 
var __prev_t = 0; 
function __js2oc(m) { 
    // It's a VERY NARROW Bridge so traffic must be throttled 
    var __now = new Date(); 
    var __curr_t = __now.getTime(); 
    var __diff_t = __curr_t - __prev_t; 
    if (__diff_t > __js2oc_wait) { 
    __prev_t = __curr_t; 
    window.location.href = "command:" + m; 
    } else { 
    __prev_t = __curr_t + __js2oc_wait - __diff_t; 
    setTimeout(function() { 
     window.location.href = "command:" + m; 
    }, (__js2oc_wait - __diff_t)); 
    } 
} 
Problemi correlati