UIWebView stringByEvaluatingJavaScriptFromString in background

前端 未结 4 1442
温柔的废话
温柔的废话 2021-02-10 01:29

In an iOS app, I\'m running a fairly large script on a UIWebView using stringByEvaluatingJavaScriptFromString (large in terms of the length of the java

相关标签:
4条回答
  • 2021-02-10 02:06

    Well, I was doing the same thing. I had to run a synchronous ajax request which was freezing my UI. So this is how I fixed it :

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

    The logic is simple. Go to a new thread, and from within that, dispatch to the main queue and then do the JS work and everything worked like a charm for me...

    0 讨论(0)
  • 2021-02-10 02:12

    No, Webviews and the Webkit JavaScript engine are both single-threaded and cannot be used on a background thread.

    A better option is to split up your JavaScript into discrete execution blocks and pipeline them using a JavaScript timer, like this (JS code, not 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();
    

    That will prevent your script from blocking user interaction while it executes

    0 讨论(0)
  • 2021-02-10 02:15

    Anything you do with a UIWebView must be done on the main thread. It's a UI element, so this is why performSelectorInBackground breaks your app.

    0 讨论(0)
  • 2021-02-10 02:16

    You could try putting that call into an NSOperation. Since you are working with a UI element, be sure to use the [NSOperationQueue mainQueue].

    0 讨论(0)
提交回复
热议问题