UIWebView stringByEvaluatingJavaScriptFromString在后台

时间:2012-02-08 15:45:41

标签: objective-c ios uiwebview

在iOS应用中,我使用UIWebViewstringByEvaluatingJavaScriptFromString上运行了一个相当大的脚本(javascript字符串的长度很大)。在调用javascript后导致屏幕上的其他元素暂时打嗝,暂停一段时间。

将javascript调用放在后台使用self performSelectorInBackground调用的函数中会破坏应用程序。有没有一种安全的方法可以在后台线程上调用run或者阻止接口暂停?

4 个答案:

答案 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]。