2012-02-08 98 views
5

在iOS应用程序中,我使用stringByEvaluatingJavaScriptFromString(在javascript字符串长度方面较大)在UIWebView上运行了一个相当大的脚本。在调用JavaScript导致屏幕上的其他元素暂时打嗝后,会有一个短暂的暂停。UIWebView stringByEvaluatingJavaScriptFromString在后台

将javascript调用放在后台调用的函数self performSelectorInBackground中可以中断应用程序。有没有一种安全的方式来调用在后台线程上运行或者以其他方式阻止接口暂停?

回答

0

您可以尝试将该调用放入NSOperation。由于您正在使用UI元素,因此请务必使用[NSOperationQueue mainQueue]。

+0

这将有助于? – 2012-02-08 17:19:07

2

你对UIWebView所做的任何事情都必须在主线程中完成。这是一个UI元素,所以这就是为什么performSelectorInBackground打破了你的应用。

3

不,Webviews和Webkit JavaScript引擎都是单线程的,不能用于后台线程。

一个更好的选择是你的JavaScript分成独立执行单元和流水线他们使用JavaScript计时器,像这样(JS代码,而不是对象 - 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(); 

这将防止您的脚本在执行时阻止用户交互

+0

谢谢。这解决了一半的问题,甚至超出了必要的范围。简单地调用所有使用简短计时器完成所有工作的功能会使暂停时间缩短。如果我理解了这个权利,一旦'stringByEvaluatingJavaScriptFromString'函数中的脚本执行主线程就可以继续,因此允许js计时器调用的函数独立运行。 仅通过调用带有大字符串的'stringByEvaluatingJavaScriptFromString',仍然存在轻微的停顿。也许像obj-c方面的这种方法可以减轻这一点。 – 2012-02-09 16:44:18

+0

而不是将整个脚本作为字符串传递,您可以将其作为脚本标记附加到页面的html,然后通过使用stringByEvaluatingJavaScriptFromString调用函数来触发它。 – 2012-02-09 16:47:41

+0

这似乎有相同的改善,但仍不是100%。 – 2012-02-09 17:42:42

3

嗯,我在做同样的事情。我不得不运行一个冻结我的UI的同步ajax请求。所以这是我如何修复它:

__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]; 
     }); 
    }); 

逻辑很简单。去一个新的线程,并从内部,派遣到主队列,然后做JS工作,一切工作像我的魅力...

相关问题