UIWebView stringByEvaluatingJavaScriptFromString在后台

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

使用self performSelectorInBackground在后台调用的函数中放置JavaScript调用会中断应用程序。 有没有一个安全的方法来调用后台线程或以其他方式防止接口暂停?

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

一个更好的select是将你的JavaScript分成独立的执行块,并使用JavaScript定时器(如JS代码,而不是Obj-C)来pipe理它们:

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

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

那么,我正在做同样的事情。 我不得不运行一个同步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工作,一切工作像一个魅力我…

任何你用UIWebView做的事都必须在主线程上完成。 这是一个UI元素,所以这就是为什么performSelectorInBackground会破坏你的应用程序。

你可以尝试把这个调用放到NSOperation中。 由于您正在使用UI元素,请务必使用[NSOperationQueue mainQueue]。