我试图理解一种设计模式,用于从SwiftUI视图中访问参与者类型中保存的隔离状态。
看看下面这个简单的代码:
actor Model: ObservableObject {
@Published var num: Int = 0
func updateNumber(_ newNum: Int) {
self.num = newNum
}
}
struct ContentView: View {
@StateObject var model = Model()
var body: some View {
Text("\(model.num)") // <-- Compiler error: Actor-isolated property 'num' can not be referenced from the main actor
Button("Update number") {
Task.detached() {
await model.updateNumber(1)
}
}
}
}
当我尝试访问隔离值时,得到编译器错误Actor-isolated property 'num' can not be referenced from the main actor
是可以理解的,但我不知道如何在视图中显示这些数据。我想知道我是否需要一个ViewModel来观察actor,并在主线程上更新自己,但得到编译时错误Actor-isolated property '$num' can not be referenced from a non-isolated context
。
class ViewModel: ObservableObject {
let model: Model
@Published var num: Int
let cancellable: AnyCancellable
init() {
let model = Model()
self.model = model
self.num = 0
self.cancellable = model.$num
.receive(on: DispatchQueue.main)
.sink { self.num = $0 }
}
}
其次,想象一下,如果这段代码确实编译了,那么当我单击主线程上的接口没有更新的按钮时,我会得到另一个错误......我再次不确定如何从actor内部实现这一点?
2条答案
按热度按时间ki1q1bka1#
您需要在视图模型(名为
Model
)上使用MainActor
,以指示其中的所有调度都在主线程上(当然,假设您将为它使用新的swift并发系统)。所以看起来
igetnqfo2#
可接受的答案可能不适合所有用例。
在我的例子中,我希望
ObservableObject
仍然是actor
,但是从SwiftUI视图访问它的一个属性,所以我只向该属性添加了@MainActor
。这意味着该属性也只需要从主线程更新,如下所示。