有什麼辦法從主線程同步查詢JavaScript?WKWebView:試圖從主線程同步查詢JavaScript
func evaluateJavaScript(_ javaScriptString: String, completionHandler completionHandler: ((AnyObject!, NSError!) -> Void)?)
異步行爲通常可以接通同步用信號量暫停線程&控制執行:
JavaScript是從使用異步函數與回調參數以處理該響應的本地代碼查詢
// 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
是總是稱爲主線程,代碼deadlo因爲completionHandler
塊永遠不會執行(主線程在最後一行被dispatch_semaphore_wait
暫停)
有什麼建議嗎?
編輯
我寧願不被阻塞主線程來執行代碼。但是,如果不將我的API從同步改爲異步,我就無法從主線程分離,並且在整個堆棧中產生多米諾骨牌效應(例如從let ua = computeUserAgent()
到computeUserAgent() {(ua: String)->Void in /*Use ua value here */}
)。所以我需要在兩種方法之間進行選擇,這兩種方法都有缺點,我寧願選擇不會混淆我內部API的方法,特別是對於像查找用戶代理一樣微不足道的任務。
當然,這裏有一個建議:不要這樣做。使用提供的功能並繼續。不要試圖顛覆異步功能。如果您阻止主線程等待,用戶將無法與您的應用程序進行交互,並且看門狗進程可能會導致應用程序死機。有合法的方式讓用戶暫時無法做任何事情,但這不是其中之一。 – matt 2015-02-07 22:47:42
@matt,我認爲你在這裏忽略了一點:據我瞭解,completionHandler似乎總是在主線程上運行,這使得很難實現evaluateJavascript調用的同步抽象化...同步不會意思是「在主線上」 – 2015-02-07 23:53:51
@StephanePhilipakis這不是他問的。他想要這個主線程(請參閱問題的標題)並且是同步的。他不應該那樣想。我的評論說「不要那樣」。 – matt 2015-02-08 00:06:57