我有以下视图模型
@MainActor
final class SomeViewModel {
func loadFromService() async {
do {
let dto = try await networkService.theServiceIneedHere()
//process dto
//state is a @Published property and observed by a SwiftUI view to update the UI.
state = .success(viewData)
}catch {
state = .failure(someError)
}
}
}
我的问题是,如果从我的 SwiftUI 视图任务方法调用 loadFromService 并且我的 SwiftUI 视图未标记为“@MainActor”,那么 loadFromService() 是否在 MainActor 线程上运行?即它不是孤立的?
以下是上述代码的更好方法吗?
final class SomeViewModel {
func loadFromService() async {
do {
let dto = try await networkService.theServiceIneedHere()
await handleServiceSuccess(with:dto)
} catch {
await MainActor.run {
state = .failure(someError)
}
}
}
}
@MainActor
private func handleServiceSuccess(with: DTO) {
//process dto, update state here
state = .success(viewData)
}
在第二种方法中,我觉得loadFromService与主线程分离,只有当我们需要更新UI时,我们才切换回主线程。
第一种方法是我的首选方法。因为这样你就不需要在更新任何 UI 参数(很可能是 @Published 属性)之前切换到主线程。
我还不熟悉新的
@Observable
,但这至少是我对 @ObservableObject
的建议,因为您将属性存储为 @Published
并在视图模型中更新它们。
如果你的
networkService.theServiceIneedHere()
没有标记为@MainActor,那么它不会被强制在主线程上。
try await callToAsync()
不继承调用 actor。
因此,在第一个示例中,您的网络调用在任何线程上完成,并且状态在主线程上更新。
SwiftUI View body getter 已在其协议中标记为 MainActor。因此,即使您使用
Task {}
,您体内的每个代码块也会在主线程上执行,因为 Task
继承了调用 actor。