10

I have the following code in viewDidLoad, which works properly on iOS 4.3, but it hangs on iOS 5/5.1. On iOS 5/5.1, the alert dialog is shown but can not be dismissed, the UI thread freezes, the OK button just can not be clicked.

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    dispatch_sync(dispatch_get_main_queue(), ^{
        [self.webview stringByEvaluatingJavaScriptFromString:@"alert('HELLO WORLD!')"];
    });
});

Is this a bug?

5
  • If you have some code that replicates this problem, please report it to developer.apple.com/bugreporter Commented Jul 21, 2012 at 16:45
  • @neevek, did you have any response from Apple with your logged bug? I am seeing the same problem in iOS 7.0.3 so I'm guessing not Commented Oct 30, 2013 at 18:23
  • @1800INFORMATION, no. Commented Oct 31, 2013 at 1:34
  • Isn't the problem the alert itself? Will the alert return immediately? Commented Mar 14, 2014 at 13:59
  • @hfossli, we have no control over the alert itself, we just pass it a string, if it does not return, it MUST be a bug. Commented Mar 15, 2014 at 1:52

4 Answers 4

18

After test, I consider it as a Bug, and changing code to use

[webView performSelectorOnMainThread:@selector(stringByEvaluatingJavaScriptFromString:) withObject:js waitUntilDone:NO]

will solve it.

Sign up to request clarification or add additional context in comments.

5 Comments

Yes I did use the alternative as you suggested and already filed this bug to Apple.
I found if the webview call "stringByEvaluatingJavaScriptFromString" in a Blocks, would cause the same problem, it freezes, after call js-alert.
This solution is not working when i use it withing block... javascript is not showing alert
This worked for me as well. Does anyone know why this is caused?? Edit: I get this issue on iOS 7.1
@Toni This is worked for us on iOS8 and solved our problem. Thanks for posting this workaround!
0

Try it in - (void)viewDidAppear:(BOOL)animated instead

1 Comment

The same as in viewDidLoad.
-1

Why are you using GCD at all here?

Remember that in GCD there is no guarantee which thread your code will called on, regardless of queue. My guess is that your DISPATCH_QUEUE_PRIORITY_DEFAULT code happens to be running on the main thread, which is then triggering a deadlock on your dispatch_sync() call. This could be verified by examining your thread states in the debugger or Instruments.

Which gets back to my original question: what do you get by doing these convolutions instead of just calling the method directly on the main thread? You are going to block either way.

You can also change your dispatch_sync() to dispatch_async() - that should also suppress a deadlock, but should only be done if you have other concurrency needs and don't need a background thread to block.

6 Comments

None of the global queues should be synchronous with respect to the main queue (which is special in that it's tied to the main thread). That's pretty much the whole point of a queue: it establishes an execution context that is asynchronous with respect to everything except itself and its target queues.
(I agree with the suggested change though)
@Catfish_Man I do not believe any promises are made as to which thread a queue will execute on. dispatch_sync() is notoriously confusing since, as the docs note, it will try to run on the current thread, potentially disregarding the target queue. This is a known source of deadlocks.
The code is just for demonstration, I use it in a situation that reading from a socket in a background thread and updating the data through stringByEvaluatingJavaScriptFromString. Anyway, the code is supposed to work without problem. My guess is dispatch_get_global_queue will not likely return a queue to be executed on the main thread. and the problem is not caused by dispatch_sync, I changed it to dispatch_async with no luck.
FYI, the code always works on iOS 4.3, and always deadlocks on iOS 5.0 and iOS 5.1, so I'd rather believe this is a bug. I changed my code to use [webView performSelectorOnMainThread:@selector(stringByEvaluatingJavaScriptFromString:) withObject:js waitUntilDone:NO] and worked without problem on all mentioned versions of iOS.
|
-1

Try

dispatch_async(dispatch_get_main_queue(), ^{
    [self.webview stringByEvaluatingJavaScriptFromString:@"alert('HELLO WORLD!')"];
});

1 Comment

It does NOT work for me, and performSelectorOnMainThread: works.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.