ios – WKWebView:尝试从主线程同步查询javascript

有没有办法从主线程同步查询 javascript

使用具有回调参数的异步函数从本机代码查询Javascript以处理响应:

func evaluateJavaScript(_ javaScriptString: String,completionHandler completionHandler: ((AnyObject!,NSError!) -> Void)?)

通常可以通过暂停线程来实现异步行为的同步.使用信号量控制执行:

// 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)

…但是在这种情况下,因为在主线程上总是调用completionHandler,所以代码死锁,因为completionHandler块永远不会执行(主线程被最后一行的dispatch_semaphore_wait暂停)

有什么建议?

编辑

我宁愿不阻止主线程执行该代码.但是我不能在不将我的API从同步变为异步的情况下从主线程中解耦,在堆栈中一直有多米诺骨牌效应(例如从let ua = computeUserAgent()到computeUserAgent(){(ua:String) – &gt ; Void in / *在这里使用ua值* /}).所以我需要选择两种方法都有缺点,我宁愿选择不会搞砸我的内部API的方法,特别是对于像查找用户代理这样简单的任务.

解决方法

如果你必须这样做……

正如对this answer评论中所建议的那样,你可以在你的信号量周围运行一个紧密的循环.

while (dispatch_semaphore_wait(sema,disPATCH_TIME_Now)) { 
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode 
                             beforeDate:[NSDate dateWithTimeIntervalSinceNow:10]];
}

相关文章

UITabBarController 是 iOS 中用于管理和显示选项卡界面的一...
UITableView的重用机制避免了频繁创建和销毁单元格的开销,使...
Objective-C中,类的实例变量(instance variables)和属性(...
从内存管理的角度来看,block可以作为方法的传入参数是因为b...
WKWebView 是 iOS 开发中用于显示网页内容的组件,它是在 iO...
OC中常用的多线程编程技术: 1. NSThread NSThread是Objecti...