我发现了一个似乎导致 WebKit 死锁的问题。如果我从我的主线程运行这段代码,我会正确地看到一个警告。我可以点击警报上的“确定”按钮,它会消失并且一切正常:
[theWebView stringByEvaluatingJavaScriptFromString:@"alert('hi');"];
如果我稍作修改,警报消息仍然会出现,但无法点击确定按钮 - 您无法关闭警报,如果您闯入应用程序,它会卡在 stringByEvaluatingJavaScriptFromString
调用:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_async(dispatch_get_main_queue(), ^{
[theWebView stringByEvaluatingJavaScriptFromString:@"alert('hi');"];
});
});
两者唯一不同的是,在第二个中,它在调度队列上下文中的主线程中运行 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];
});
有人可以阐明导致挂起的问题吗?
编辑:
相关问题:
Perform UI Changes on main thread using dispatch_async or performSelectorOnMainThread?
Whats the difference between performSelectorOnMainThread and dispatch_async on main queue?
Grand Central Dispatch (GCD) vs. performSelector - need a better explanation
非常相似的问题:
UIWebView stringByEvaluatingJavaScriptFromString hangs on iOS5.0/5.1 when called using GCD
最佳答案
我认为它在 webview 中有说明类引用
现在,对于你的死锁情况,你可以通过替换这个来模拟相同的情况
[self performSelectorOnMainThread:@selector(showHi:) withObject:theWebView waitUntilDone:NO];
与
performSelector:withObject:afterDelay:inModes:
。
对于 Respective 模式,默认情况下它是 NSDefaultRunLoopMode
,它本质上是原子的,而在 dispatch_get_main_queue()
的非原子情况下,您必须更改线程的当前调度模式。
我希望它能提供有用的信息。另外,欢迎提出更多建议。
关于ios - GCD 和 webView 的死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19531701/