2012-02-08 22 views
5

En una aplicación de iOS, ejecuto un script bastante grande en UIWebView usando stringByEvaluatingJavaScriptFromString (grande en términos de la longitud de la cadena javascript). Hay una breve pausa después de llamar al javascript, causando que otros elementos en la pantalla se contraigan por un momento.UIWebView stringByEvaluatingJavaScriptFromString en el fondo

Al colocar la llamada javascript en una función llamada en el fondo con self performSelectorInBackground se rompe la aplicación. ¿Existe una forma segura de ejecutar ejecutar esto en un hilo de fondo o evitar que la interfaz se pause?

Respuesta

0

Puede intentar poner esa llamada en una NSOperation. Como está trabajando con un elemento de IU, asegúrese de usar la [NSOperationQueue mainQueue].

+0

¿Cómo ayudará eso? –

2

Cualquier cosa que hagas con un UIWebView debe hacerse en el hilo principal. Es un elemento de UI, por eso performSelectorInBackground rompe tu aplicación.

3

No, Webviews y el motor JavaScript de Webkit son de un solo subproceso y no se pueden utilizar en una cadena de fondo.

Una mejor opción es dividir el JavaScript en bloques de ejecución discretos y tubería de ellas utilizando un temporizador de JavaScript, como esto (código JS, no Obj-C):

var i = 0; 
var operation = function() { 

    switch (i) { 
    case 0: 
     //do first part of code 
     break; 
    case 1: 
     //do second part of code 
     break; 
    case 2: 
     //do third part of code 
     break; 
    etc... 
    } 

    //prepare to execute next block 
    i++; 
    if (i < TOTAL_PARTS) { 
     setTimeout(operation, 0); 
    } 
}; 
operation(); 

que evitará que su script desde bloqueo de la interacción del usuario mientras se ejecuta

+0

Gracias. Esto resuelve la mitad del problema e incluso es un poco más de lo necesario. Simplemente llamando a la función que hace todo el trabajo con un breve temporizador hace que la pausa sea mucho más corta. Si entiendo esto bien, una vez que se ejecuta el script en la función 'stringByEvaluatingJavaScriptFromString', el hilo principal puede continuar, por lo que la función invocada por el temporizador js puede ejecutarse de manera independiente. Todavía hay una pequeña pausa simplemente al llamar 'stringByEvaluatingJavaScriptFromString' con una cadena grande. Tal vez algo como este enfoque en el lado obj-c podría aliviar eso. –

+0

En lugar de pasar toda la secuencia de comandos como una cadena, podría agregarla como una etiqueta de script al html de su página y luego simplemente activarla invocando una función con stringByEvaluatingJavaScriptFromString. –

+0

Parece que tiene la misma mejora, pero todavía no es 100%. –

3

Bueno, yo estaba haciendo lo mismo. Tuve que ejecutar una solicitud síncrona ajax que congelaba mi UI. Así que así es como lo arreglé:

__block NSString *message; 
    dispatch_queue_t q = dispatch_queue_create("sign up Q", NULL); 
    dispatch_async(q, ^{ 
     NSString *function = [[NSString alloc] initWithFormat: @"signup(\'%@\',\'%@\',\'%@\')",self.email.text,self.password.text,self.name.text]; 

     dispatch_async(dispatch_get_main_queue(), ^{ 
      NSString *result = [self.webView stringByEvaluatingJavaScriptFromString:function]; 
      NSLog(@"%@",result); 

      if ([result isEqualToString:@"1"]) { 
       message = [NSString stringWithFormat:@"Welcome %@",self.name.text]; 
       [self.activityIndicator stopAnimating]; 
       [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; 
      } 

      else { 
       message = [NSString stringWithFormat:@"%@ is a registered user",self.name.text]; 
       [self.activityIndicator stopAnimating]; 
       [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; 
      } 

      UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Message" message:message delegate:self cancelButtonTitle:@"Okay" otherButtonTitles: nil]; 
      [alertView show]; 
     }); 
    }); 

La lógica es simple. Ir a un nuevo hilo, y desde allí, despachar a la cola principal y luego hacer el trabajo de JS y todo funcionó como un amuleto para mí ...

Cuestiones relacionadas