180*_*ION 6 webkit objective-c grand-central-dispatch ios
我发现了一个似乎导致WebKit陷入僵局的问题.如果我从我的主线程运行此代码,我正确地看到一个警报.我可以点击警报上的"确定"按钮,它会解散并且一切正常:
[theWebView stringByEvaluatingJavaScriptFromString:@"alert('hi');"];
Run Code Online (Sandbox Code Playgroud)
如果我进行了一些修改,那么警报信息仍会出现,但是无法点击"确定"按钮 - 您无法关闭警报,如果您闯入应用程序,它将挂在stringByEvaluatingJavaScriptFromString通话中:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_async(dispatch_get_main_queue(), ^{
[theWebView stringByEvaluatingJavaScriptFromString:@"alert('hi');"];
});
});
Run Code Online (Sandbox Code Playgroud)
这两者中唯一不同的是,在第二个中,它在调度队列的上下文中在主线程中运行JS.
另一方面,如果我执行以下操作,则不会发生挂起:
- (void) showHi:(id) it
{
[(UIWebView*)it stringByEvaluatingJavaScriptFromString:@"alert('hi');"];
}
....
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self performSelectorOnMainThread:@selector(showHi:) withObject:theWebView waitUntilDone:NO];
});
Run Code Online (Sandbox Code Playgroud)
有人可以对导致挂起的问题有所了解吗?
编辑:
相关问题:
使用dispatch_async或performSelectorOnMainThread在主线程上执行UI更改?
什么是主队列上的performSelectorOnMainThread和dispatch_async之间的区别?
Grand Central Dispatch(GCD)与performSelector - 需要更好的解释
非常相似的问题:
当使用GCD调用时,UIWebView stringByEvaluatingJavaScriptFromString在iOS5.0/5.1上挂起
我认为它是在webview中说明的
课堂参考
现在,对于死锁的情况,您可以通过替换它来模拟相同的情况
[self performSelectorOnMainThread:@selector(showHi:) withObject:theWebView waitUntilDone:NO];
同
performSelector:withObject:afterDelay:inModes:.默认情况下使用"分别"模式,它NSDefaultRunLoopMode本质上是原子的,而在非原子模式下,dispatch_get_main_queue()您必须更改当前的线程分派模式.
我希望它仍然有用.此外,欢迎提出更多建议.
这似乎只是 UIWebView 中的一个错误。根据这个问题,它是在iOS 5中引入的,并且在iOS 4.3及以下版本上没有死锁。
有趣的是,在调用之前呈现 UIAlertView 可以stringByEvaluatingJavaScriptFromString:奇怪地防止死锁:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertView *message = [[UIAlertView alloc] initWithTitle:@"Test"
message:@"Test"
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[message show];
[theWebView stringByEvaluatingJavaScriptFromString:@"alert('hi');"];
});
});
Run Code Online (Sandbox Code Playgroud)
然而,我的理论是这样的:当我在死锁发生后暂停执行时,我看到 WebThread 停止在__psynch_mutexwait。由于 JavaScript 引擎在不同的线程上执行,因此它必须告诉主线程显示警报视图。但是,stringByEvaluatingJavaScriptFromString:这是一个返回值的阻塞调用。仅当通过单击“确定”解除警报后才能返回该值。这就是死锁似乎发生的地方:从另一个线程,我们告诉主线程告诉 Web 视图运行 JavaScript(这发生在另一个线程上),这又告诉主线程显示一个警报视图,该视图只能单击“确定”后,将其返回值传递回 JavaScript。只有当调用stringByEvaluatingJavaScriptFromString:return 时,我们传递给 GCD 的块才完成。
不过,这一定是一个错误。奇怪的是,当我首先显示 UIAlertView 时,并没有发生死锁。也许在这种情况下,iOS 将第二个警报视图放在某种队列上,这可以防止死锁。奇怪的!
| 归档时间: |
|
| 查看次数: |
4073 次 |
| 最近记录: |