我真的認為,如果 Swift 中的代碼在 iOS 中異步運行,那么就其本身而言,它運行在一個單獨的執行緒上,而不是呼叫代碼的執行緒 - 通常是主執行緒。這對我來說似乎很明顯,但我不確定并希望收到驗證。我想不出任何情況下異步代碼會在呼叫它的同一代碼上運行。根據定義,異步代碼運行在與呼叫它的執行緒不同的執行緒上似乎幾乎是肯定的。
你怎么認為?你會同意并驗證這一點嗎?
我在嘗試理解 @escaping 關鍵字時問這個問題,因為它適用于完成處理程式。關于閉包的 Swift 檔案說@escaping 關鍵字導致指定為轉義的完成處理程式異步運行并在函式(接收完成閉包作為引數)完成運行后運行。然而,檔案沒有說明轉義完成處理程式是在不同的執行緒上運行還是在當前執行緒上運行——這將是主/UI 執行緒。
我試圖尋找運行時錯誤的來源。錯誤訊息說:“從主執行緒訪問布局引擎后,不得從后臺執行緒執行對布局引擎的修改。”
它可能來自CNContactStore requestAccess(for:completionHandler:)的完成處理程式,但我需要知道 @escaping 是否導致它適用的閉包在與呼叫閉包的執行緒不同的執行緒上運行,因為 completionHandler引數在CNContactStore requestAccess(for:completionHandler:)的定義中通過@escaping關鍵字定義為轉義。
我收到的錯誤是否來自該函式的完成處理程式中的代碼,該函式修改了布局引擎或任何標記為轉義的完成處理程式?
stackoverflow 上的這些帖子幫助我澄清了我的問題,但它們沒有回答我的問題:
異步代碼是在 UI 執行緒中運行還是在新的/不同的執行緒中運行以不阻塞 UI?
異步 - 留在當前執行緒上?
uj5u.com熱心網友回復:
@escaping不決定關閉在哪個執行緒上運行。檔案確實如此。
對于該特定功能(https://developer.apple.com/documentation/contacts/cncontactstore/1402873-requestaccess/):
系統在任意佇列上執行 completionHandler。建議您在此完成處理程式中使用 CNContactStore 實體方法而不是 UI 主執行緒。
如果您在completionHandler回呼中執行任何型別的 UI 作業,這意味著您必須呼叫DispatchQueue.main.async { update_my_UI_here() }以在主執行緒上安全地執行您的代碼。
例子:
requestAccess(for: .contacts) { [weak self] permissionGranted, error in
//All code in here is ran on an ARBITRARY background queue
if let error = error {
log(error)
return
}
//CNContactStore - Any CNContactStore functions should run here, and not inside `DispatchQueue.main`
guard let self = self else { return }
// Any UI updates or any code that interacts with `UI*` or constraints, must be done on main
DispatchQueue.main.async {
self.update_my_ui_here(permisionGranted) //Safely update UI from the main queue
}
}
將函式標記為@escaping僅僅意味著它可能會在以后被呼叫或作為變數存盤在某處。這就是全部意思。這并不意味著它將在相同或不同的執行緒上運行。它沒有關于執行緒的任何保證,也沒有關于何時運行的任何保證。
畢竟,DispatchQueue.main.async(completion: @escaping () -> Void)有一個轉義引數,但它總是completion在完全相同的main執行緒上運行。main是唯一具有這種保證的佇列,無論引數是否轉義。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/371248.html
上一篇:如何從物體向量中找到最小值?
