在iOS应用中,我使用UIWebView
在stringByEvaluatingJavaScriptFromString
上运行了一个相当大的脚本(javascript字符串的长度很大)。在调用javascript后导致屏幕上的其他元素暂时打嗝,暂停一段时间。
将javascript调用放在后台使用self performSelectorInBackground
调用的函数中会破坏应用程序。有没有一种安全的方法可以在后台线程上调用run或者阻止接口暂停?
答案 0 :(得分:3)
不,Webviews和Webkit JavaScript引擎都是单线程的,不能在后台线程上使用。
更好的选择是将JavaScript拆分为离散的执行块,并使用JavaScript计时器对它们进行管道处理,如下所示(JS代码,而不是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();
这将阻止您的脚本在执行时阻止用户交互
答案 1 :(得分:3)
嗯,我做的是同样的事情。我不得不运行同步ajax请求,这会冻结我的UI。所以这就是我修复它的方法:
__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工作,一切都像我的魅力...
答案 2 :(得分:2)
使用UIWebView
执行的任何操作都必须在主线程上完成。它是一个UI元素,所以这就是performSelectorInBackground
打破你的应用程序的原因。
答案 3 :(得分:0)
您可以尝试将该调用放入NSOperation中。由于您正在使用UI元素,请务必使用[NSOperationQueue mainQueue]。