【问题标题】:Accessing an actor's isolated state from within a SwiftUI view从 SwiftUI 视图中访问参与者的隔离状态
【发布时间】:2021-10-13 04:23:14
【问题描述】:

我试图了解一种设计模式,用于从 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-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 }
    }
    
}

其次,想象一下如果这段代码确实编译了,那么当我点击主线程上的界面没有更新的按钮时,我会得到另一个错误......再次,我不确定如何从演员内部实现这一点?

【问题讨论】:

    标签: swift concurrency swiftui


    【解决方案1】:

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

    它看起来像

    @MainActor 
    class Model: ObservableObject {
        @Published var num: Int = 0
    
        func updateNumber(_ newNum: Int) {
            self.num = newNum
        }
    }
    

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

    【讨论】:

    • 谢谢。在您的笔记中,我是否理解最好写:func updateNumber(_ newNum: Int) { Task.detached() { await model.updateNumber(newNum) }}
    • 我是否也正确理解在 SwiftUI 应用程序中所有同步都将通过 @MainActor 发生,因此不会使用 actor 创建任何类型?
    猜你喜欢
    • 2021-08-29
    • 1970-01-01
    • 1970-01-01
    • 2020-05-24
    • 1970-01-01
    • 2020-11-22
    • 2022-10-19
    • 1970-01-01
    • 2020-11-08
    相关资源
    最近更新 更多