UIWebView stringByEvaluatingJavaScriptFromString в фоновом режиме - PullRequest
5 голосов
/ 08 февраля 2012

В приложении для iOS я запускаю довольно большой скрипт на UIWebView, используя stringByEvaluatingJavaScriptFromString (большой с точки зрения длины строки javascript). После вызова javascript возникает небольшая пауза, из-за которой другие элементы на экране на мгновение перестают работать.

Размещение вызова javascript в функции, вызываемой в фоновом режиме с self performSelectorInBackground, нарушает работу приложения. Есть ли безопасный способ вызвать запуск этого в фоновом потоке или иным образом предотвратить приостановку интерфейса?

Ответы [ 4 ]

3 голосов
/ 18 марта 2013

Ну, я делал то же самое. Я должен был выполнить синхронный запрос 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, и все для меня сработало ...

3 голосов
/ 08 февраля 2012

Нет, веб-представления и движок 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();

Это предотвратит блокировку взаимодействия с пользователем во время его выполнения

2 голосов
/ 08 февраля 2012

Все, что вы делаете с UIWebView, должно выполняться в главном потоке.Это элемент пользовательского интерфейса, поэтому performSelectorInBackground ломает ваше приложение.

0 голосов
/ 08 февраля 2012

Вы можете попробовать поместить этот вызов в NSOperation. Поскольку вы работаете с элементом пользовательского интерфейса, обязательно используйте [NSOperationQueue mainQueue].

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...