2015-02-07 47 views
8

有什麼辦法從主線程同步查詢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的方法,特別是對於像查找用戶代理一樣微不足道的任務。

+0

當然,這裏有一個建議:不要這樣做。使用提供的功能並繼續。不要試圖顛覆異步功能。如果您阻止主線程等待,用戶將無法與您的應用程序進行交互,並且看門狗進程可能會導致應用程序死機。有合法的方式讓用戶暫時無法做任何事情,但這不是其中之一。 – matt 2015-02-07 22:47:42

+0

@matt,我認爲你在這裏忽略了一點:據我瞭解,completionHandler似乎總是在主線程上運行,這使得很難實現evaluateJavascript調用的同步抽象化...同步不會意思是「在主線上」 – 2015-02-07 23:53:51

+0

@StephanePhilipakis這不是他問的。他想要這個主線程(請參閱問題的標題)並且是同步的。他不應該那樣想。我的評論說「不要那樣」。 – matt 2015-02-08 00:06:57

回答

2

如果必須做到這一點...

正如評論建議this answer你可以運行在你的信號燈等待這樣一個緊密的循環。

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

Kludgy,但它是一個工作答案,謝謝你的問題!還不太確定我將用於我的項目(特別是,@matt在問題的評論部分中提供了一些優點),但明天我會接受該答案,除非有更好的答案通過 – Hugo 2015-02-08 05:32:44

+0

您好。我測試了你的解決方案,它不工作。完成處理程序仍然被阻止,但仍然沒有執行:/ – h3dkandi 2016-04-21 14:39:53

+0

它可能會導致崩潰! – Nikita 2016-12-15 12:31:08