2012-09-15 11 views
12

Estoy buscando diferentes métodos para inyectar JavaScript en una WebView (en Cocoa).Métodos de inyección de JavaScript usando Objective-C

Estoy tratando de insertar algo de javascript en la etiqueta <head> de un archivo HTML que se ha cargado en WebView.

El siguiente método no funciona para mí. Parece que funciona únicamente con muy simple JavaScript con no hay corchetes anidados (por lo que he probado):

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

¿Hay otras formas de hacer esto con más complicadas funciones JavaScript/jQuery?

El código completo que estoy tratando de inyectar es el siguiente:

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

Respuesta

8

No puede usar jQuery para agregar etiquetas <script>. Esto ha sido preguntado muchas veces. Ver:

usted puede hacerlo con el navegador incorporado en funciones, pero:

¿funcionaría sólo asignar su función a una variable en su página y luego evaluarlo? Algo así como:

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

actualización ejemplos explícitos:

Debe utilizar el ejemplo anterior como plantilla!

De todos modos, hay 2 partes en el proceso ... La parte Javascript y la parte Objective-C. A nivel de Javascript, que está haciendo esto:

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

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

También puede hacerlo sin asignar la función a una variable, por ejemplo, si no se preocupan por referencia a la función en el futuro. Al hacerlo sin una variable y utilizando una función anónima se ve así:

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

i.e.en lugar de hacer var A = <the function>; A(); que está haciendo (<the function>)();

Por último, si su función anónima toma argumentos, como es tu caso, el patrón se ve así:

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

Usando esto como una plantilla para su código, sus extremos JS arriba como:

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

Entonces, eso es lo que quiere la vista web para ejecutar ... ese es el código pasamos a la vista web. Pero debe compilar esa cadena en su programa Obj-C, con la "complicación" de insertar el argumento de tiempo actual (123.456 en el código anterior).

Parece que este:

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 ] ; 

creo que he escrito lo suficiente ahora :)

+0

funciona el ejemplo anterior, y el resultado = "éxito" está impreso en la consola. Sin embargo, cuando uso mi propio javascript en lugar de "éxito", las comillas en blanco se imprimen en la consola. ¿Algunas ideas? –

+0

Si desea ejecutar su función una vez, cambie su código para que sea '(function() {...})()' – nielsbot

+0

Si va a utilizar su función varias veces, use 2 pasos. Asigna tu función a una variable ('submitFormForTime = function (time) {...}') luego cada vez que quieras ejecutar tu función haz 'submitFormForTime (...)'. – nielsbot

0

me gustaría tener todo el código HTML de la página we, entonces me inyecto el código y volver a cargar la página. Todavía no es un método adecuado de inyección, pero puede funcionar.

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

Por supuesto que puede tener la URL base de su solicitud, si es así, reemplace esa nula.

0

No probé esto, pero si el problema es con los corchetes y la complejidad del código, puede intentar llamar a un archivo JS almacenado en el paquete. Tal vez eso resuelva eso. Por ejemplo:

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

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

[webView stringByEvaluatingJavaScriptFromString:jsString]; 

Tal vez la configuración del tipo de codificación ayuda a analizar todos los corchetes de una manera correcta.

Cuestiones relacionadas