Hug*_*ugo 8 semaphore grand-central-dispatch ios ios8 wkwebview
有没有办法从主线程同步查询javascript?
使用具有回调参数的异步函数从本机代码查询Javascript以处理响应:
func evaluateJavaScript(_ javaScriptString: String, completionHandler completionHandler: ((AnyObject!, NSError!) -> Void)?)
Run Code Online (Sandbox Code Playgroud)
通过暂停线程并使用信号量控制执行,通常可以将异步行为转为同步:
// Executing in the main thread
let sema = dispatch_semaphore_create(0)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {
// Background thread
self.evaluateJavaScript("navigator.userAgent", completionHandler: { (value:AnyObject!, error: NSError!) -> Void in
if let ua = value as? String {
userAgent = ua
} else {
ERROR("ERROR There was an error retrieving the default user agent, using hardcoded value \(error)")
}
dispatch_semaphore_signal(sema)
})
}
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER)
Run Code Online (Sandbox Code Playgroud)
然而......在这种情况下,因为completionHandler是一直被称为主线程,代码死锁,因为completionHandler块永远不会执行(主线程暂停由dispatch_semaphore_wait在最后一行)
有什么建议?
编辑
我宁愿不阻止主线程执行该代码.但是我不能在不将我的API从同步变为异步的情况下从主线程中解耦,并且在堆栈中一直有多米诺骨牌效应(例如从let ua = computeUserAgent()到computeUserAgent() {(ua: String)->Void in /*Use ua value here */}).因此,我需要选择两种方法都有缺点,我宁愿选择不会弄乱我的内部API的方法,特别是对于像查找用户代理这样简单的任务.
如果你必须这样做...
正如对此答案的评论中所建议的,您可以像这样围绕信号量等待运行紧密循环。
while (dispatch_semaphore_wait(sema, DISPATCH_TIME_NOW)) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:[NSDate dateWithTimeIntervalSinceNow:10]];
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3342 次 |
| 最近记录: |