从 SwiftUI 视图中访问参与者的隔离状态 [英] Accessing an actor's isolated state from within a SwiftUI view

查看:28
本文介绍了从 SwiftUI 视图中访问参与者的隔离状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图了解一种设计模式,用于从 SwiftUI 视图中访问 actor 类型中保存的隔离状态.

I'm trying to understand a design pattern for accessing the isolated state held in an actor type from within a SwiftUI view.

拿这个简单的代码:

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 main actor.但是我无法理解如何在视图中显示这些数据.我想知道我是否需要一个 ViewModel 来观察演员,并在主线程上更新自己,但得到编译时错误 Actor-isolated property '$num' can not be referenced from a non-isolated context.

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 }
    }
    
}

其次,想象一下,如果这段代码确实编译了,那么在单击主线程上未更新界面的按钮时,我会收到另一个错误...同样,我不确定如何从 actor 内部实现这一点?

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?

推荐答案

您需要在您的视图模型(名为 Model)上使用 MainActor 表示其中的所有调度在主线程上(当然假设您将使用新的 swift 并发系统).

You need to use MainActor on your view model (named Model) indicating that all dispatching in it be on main thread (of course assuming you will use new swift concurrency system for it).

所以它看起来像

@MainActor 
class Model: ObservableObject {
    @Published var num: Int = 0

    func updateNumber(_ newNum: Int) {
        self.num = newNum
    }
}

注意:我建议在课堂内进行所有更新,因为某个地方的某些人可能会忘记以正确的方式更新它.

这篇关于从 SwiftUI 视图中访问参与者的隔离状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆