2012-09-15 3 views
12

Sto cercando diversi metodi per l'iniezione di JavaScript in una WebView (in Cocoa).Metodi di iniezione JavaScript utilizzando Objective-C

Sto cercando di inserire del javascript nel tag <head> di un file HTML che è stato caricato in WebView.

Il seguente metodo non funziona per me. Sembra funzionare solo con molto semplice JavaScript con senza parentesi nidificate (da quello che ho testato):

[webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"var script = document.createElement('script');" 
                "script.type = 'text/javascript';" 
                "script.text = \"some simple JavaScript" 
                "}\";" 
                "document.getElementsByTagName('head')[0].appendChild(script);"]]; 

ci sono altri modi per farlo con più complicate funzioni JavaScript/jQuery?

Il codice completo che sto cercando di iniettare è il seguente:

function submitFormForTime(time){ 
    $(\".t_h\").each(function(i, obj) { 
     if ($(this).text() != time) return; 
     $(this).parent().find(\"form\").each(function(i, obj){ 
      obj.submit(); 
     }); 
    }); 
} 

risposta

8

Non è possibile utilizzare jQuery per aggiungere i tag <script>. Questo è stato chiesto più volte. Vedi:

si può fare con il browser funzioni built-in, MA:

dovrebbe funzionare per assegnare solo la funzione a una variabile sulla tua pagina e poi valutarlo? Qualcosa di simile:

-(void)webViewDidFinishLoad:(UIWebView *)webView 
{ 
    // add function to page: 
    NSString * js = @"myFunction = function(){ return \"success!\"; }" ; 
    [ webView stringByEvaluatingJavaScriptFromString:js ] ; 

    // execute newly added function: 
    NSString * result = [ webView stringByEvaluatingJavaScriptFromString:@"myFunction();"] ; 
    NSLog(@"result=\"%@\"", result) ; 
} 

aggiornamento esempi espliciti:

Si dovrebbe usare la mia precedente esempio come modello!

In ogni caso, ci sono 2 parti nel processo ... La parte Javascript e la parte Objective-C. A livello di Javascript, si sta facendo questo:

// assign a function to the variable "someFunction": 
var someFunction = function(){...}; 

// call the function in the variable "someFunction": 
someFunction(); 

È anche possibile farlo senza assegnare la funzione a una variabile, ad esempio, se non si cura di riferimento alla funzione in futuro. Farlo senza una variabile e utilizzando una funzione anonima è simile al seguente:

(function(){...})() ; 

vale a direinvece di fare var A = <the function>; A(); si sta facendo (<the function>)();

Infine, se la funzione anonima prende argomenti, come il vostro fa, il modello è simile al seguente:

(function(var0, ..., varN){...})(arg0, ..., argN); 

Utilizzando che come modello per il codice, i tuoi JS estremità su come:

(function(time) { 
    $(\".t_h\").each(function(i, obj) 
    { 
     if ($(this).text() != time) return; 

     $(this).parent().find(\"form\").each(function(i, obj) { 
      obj.submit(); 
     }); 
    }); 
})(123.456); 

Quindi, questo è ciò che si desidera che la visualizzazione web di eseguire ... Questo è il codice passiamo alla WebView. Ma devi costruire quella stringa nel tuo programma Obj-C, con la "complicazione" di inserire l'argomento del tempo corrente (123.456 nel codice sopra).

Ecco come si presenta:

NSString * jsTemplate = 
    @"(function(time) {" 
    @"  $(\".t_h\").each(function(i, obj) {" 
    @"   if ($(this).text() != time) return;" 
    @"   $(this).parent().find(\"form\").each(function(i, obj) {" 
    @"    obj.submit();" 
    @"   });" 
    @"  });" 
    @" })(%g);" ; 
NSString * js = [ NSString stringWithFormat:jsTemplate, 123.456 ] ; 
NSString * result = [ webView stringByEvaluatingJavaScriptFromString:js ] ; 

Penso di aver scritto abbastanza adesso :)

+0

vostro sopra esempio funziona, e il risultato = "successo!" è stampato nella console. Tuttavia, quando utilizzo il mio javascript anziché "success", nella console vengono stampate virgolette vuote. Qualche idea? –

+0

Se si desidera eseguire la funzione una volta, modificare il codice in modo che sia '(function() {...})()' – nielsbot

+0

Se si intende utilizzare la funzione più volte, utilizzare 2 passaggi. Assegna la tua funzione a una variabile ('submitFormForTime = function (time) {...}') quindi ogni volta che vuoi eseguire la tua funzione fai 'submitFormForTime (...)'. – nielsbot

0

vorrei avere tutto il codice HTML da vista web, quindi mi piacerebbe iniettare il codice e ricaricare la pagina. Non è ancora un metodo corretto di iniezione, ma potrebbe funzionare.

NSString *htmlDataString = [webView stringByEvaluatingJavaScriptFromString: @"document.documentElement.outerHTML"]; 
// use nsstring methds to find the place for injecting 
// inject avascript code 
[webView loadHTMLString:htmlDataString baseURL:nil]; 

Naturalmente si possono avere URL di base dalla vostra richiesta, in caso affermativo sostituire quel nullo.

0

Non ho provato questo, ma se il problema è con le parentesi e la complessità del codice, è possibile provare a chiamare un file JS memorizzato nel pacchetto. Forse lo risolve. Ad esempio:

NSData *fileData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@”submitFormForTime” ofType:@”js”]]; 

NSString *jsString = [[NSMutableString alloc] initWithData:fileData encoding:NSUTF8StringEncoding]; 

[webView stringByEvaluatingJavaScriptFromString:jsString]; 

Forse l'impostazione del tipo di codifica consente di analizzare tutte le parentesi nel modo corretto.