I'm trying to understand a design pattern for accessing the isolated state held in an actor type from within a SwiftUI view.
Take this naive code:
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)
}
}
}
}
Understandably I get the compiler error Actor-isolated property 'num' can not be referenced from the main actor when I try and access the isolated value. Yet I can't understand how to display this data in a view. I wonder if I need a ViewModel that observes the actor, and updates itself on the main thread, but get compile time error 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 }
}
}
Secondly, imagine if this code did compile, then I would get another error when clicking the button that the interface is not being updated on the main thread...again I'm not sure how to effect this from within the actor?