为什么 SwiftUI 视图模型要使用 @MainActor 注解?

问题描述 投票:0回答:2

我一直在观看 Apple 在 WWDC21 上的并发演讲,并阅读了大量有关 Apple 并发更新的文章;但是,我无法理解一件事:为什么人们会提供应该使用

@MainActor
注释视图模型的指导?根据我的阅读,通过将视图模型属性设置为视图中的
@StateObject
@ObservedObject
,它会自动变为
@MainActor
。那么如果是这样的话,为什么人们仍然建议将视图模型注释为
@MainActor

对于上下文,以下是我读过的一些引用此内容的文章:

  1. https://www.hackingwithswift.com/quick-start/concurrency/understanding-how-global-actor-inference-works
  2. https://www.hackingwithswift.com/books/concurrency/how-to-use-mainactor-to-run-code-on-the-main-queue
  3. https://peterfriese.dev/swiftui-concurrency-essentials-part1/

摘自第一个链接:

[A]任何使用带有 @MainActor 的属性包装器作为其包装值的结构或类将自动成为 @MainActor。这就是 @StateObject 和 @ObservedObject 在使用它们的 SwiftUI 视图上传达主要角色的原因 - 如果您在 SwiftUI 视图中使用这两个属性包装器中的任何一个,整个视图也会变成 @MainActor。

摘自第二个链接:

[W]每当你在视图中使用 @StateObject 或 @ObservedObject 时,Swift 都会确保整个视图在主要参与者上运行,这样你就不会意外地尝试以危险的方式发布 UI 更新。更好的是,无论您使用什么属性包装器,SwiftUI 视图的 body 属性始终在主要参与者上运行。

这是否意味着您不需要显式地将 @MainActor 添加到可观察对象中?嗯,不 – 在这些类中使用 @MainActor 仍然有好处,尤其是如果它们使用 async/await 来完成自己的异步工作,例如从服务器下载数据。

总而言之,如果指导会自动为我们处理,我有点困惑。特别是因为我不知道在 SwiftUI 中是否有一个不是

@ObservableObject
的视图模型。

我的最后一个问题,与第一个问题相关,是:如果

@StateObject
@ObservedObject
自动创建视图
@MainActor
,那么
@EnvironmentObject
也创建视图
@MainActor
吗?

为了在这背后放置一些代码,我打算使用

.environmentObject(...)

将以下类注入到环境中
@MainActor
class UserSettings: ObservableObject {
    @Published var flowUser: FlowUser?
    
    init(flowUser: FlowUser? = nil) {
        self.flowUser = flowUser
    }
}

以下是我的观点之一的视图模型:

@MainActor
class CatalogViewModel: ObservableObject {
    @Published var flowUser: FlowUser?
    
    init(flowUser: FlowUser?) {
        self.flowUser = flowUser
    }
}

如你所见,我已经创建了两个类

@ObservableObjects
所以我觉得我应该能够删除
@MainActor
注释。

任何帮助将不胜感激!感谢您的宝贵时间!

ios swift swiftui actor swift-concurrency
2个回答
6
投票

@ObservedObject 或其他对象并不使其成为主要参与者。所以你的说法不正确

参见 https://developer.apple.com/videos/play/wwdc2021/10019/ 大约第 22 分钟

根据我所读到的内容,通过将视图模型属性设置为视图中的 @StateObject 或 @ObservedObject,它会自动变为 @MainActor。


0
投票

我的理解是这样的

  1. 如果您的 ViewModel 可能在 SwiftUI 以外的上下文中使用(例如,在应用程序的基于 UIKit 的部分或更通用的 Swift 上下文中),则使用 @MainActor 显式标记它可以确保它的行为正确。我们都知道 SwiftUI 视图本质上是主线程绑定的,它们的生命周期和状态更改是在主线程上管理的,但如果您的 viewModel 在其他地方使用,情况可能并非如此。
  2. 使用 @MainActor 显式注释 ViewModel 可以向任何阅读代码的人表明这是打算在主线程上使用的。对于较大的团队来说,这有助于提高可读性。
© www.soinside.com 2019 - 2024. All rights reserved.