今天,我將 SwiftUI 視圖的 ViewModel 重構為結構化并發。它觸發一個網路請求,當請求回傳時,更新一個@Published屬性以更新 UI。由于我使用 aTask來執行網路請求,因此我必須回傳到MainActor更新我的屬性,并且我正在探索不同的方法來做到這一點。一種直接的方法是MainActor.run在 my 內部使用Task,效果很好。然后我嘗試使用@MainActor,并且不太了解這里的行為。
稍微簡化一下,我的 ViewModel 看起來有點像這樣:
class ContentViewModel: ObservableObject {
@Published var showLoadingIndicator = false
@MainActor func reload() {
showLoadingIndicator = true
Task {
try await doNetworkRequest()
showLoadingIndicator = false
}
}
@MainActor func someOtherMethod() {
// does UI work
}
}
我本來預計這不能正常作業。
首先,我希望 SwiftUI 會抱怨showLoadingIndicator = false發生在主執行緒之外的事情。它沒有。所以我放了一個斷點,似乎甚至Task在@MainActor主執行緒上運行。為什么這可能是另一天的問題,我想我還沒有完全弄清楚Task。現在,讓我們接受這一點。
所以我本來希望 UI 在我的 networkRequest 期間被阻止 - 畢竟,它是在主執行緒上運行的。但事實也并非如此。網路請求運行,UI 在此期間保持回應。即使在主要參與者(例如)上呼叫另一個方法也someOtherMethod完全可以正常作業。即使運行類似 inside的
東西仍然可以完全正常作業。這很好,但我想知道為什么。Task.sleep()doNetworkRequest
我的問題:
a)我是否正確假設 a Taskwithin aMainActor不會阻塞 UI?為什么?b)這是一種明智的方法,還是我會因為像這樣調度異步作業而
遇到麻煩?@MainActor
uj5u.com熱心網友回復:
await是 Swift 中的一個屈服點。這是當前任務釋放佇列并允許其他東西運行的地方。所以在這一行:
try await doNetworkRequest()
您的任務將放開主佇列,并安排其他事情。它不會阻塞等待它完成的佇列。
這意味著在await回傳之后,主要參與者可能已經運行了其他代碼,因此您不能信任在await.
目前沒有簡單的內置方式說“阻止這個演員直到完成”。演員是可重入的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/452937.html
