swift 斯威夫特,演员:无法从非隔离的内容中变更参与者隔离的属性'scanning'

xdnvmnnf  于 2022-11-21  发布在  Swift
关注(0)|答案(2)|浏览(132)

我有一个演员:

actor StatesActor {

    var job1sActive:Bool = false
    ...

}

我有一个对象使用了那个演员:

class MyObj {
    
    let myStates = StatesActor()
    
    func job1() async {
    
        myStates.job1IsActive = true

    }
}

线路:
myStates.job1IsActive = true
错误,错误为:
无法从非隔离的内容变更参与者隔离的属性'job 1 IsActive'
如何使用actor正确地存储/读取状态信息,以便MyObj可以使用它来读取和设置状态?

mhd8tkvw

mhd8tkvw1#

如何使用actor正确地存储/读取状态信息,以便MyObj可以使用它来读取和设置状态?
你不能从参与者的外部改变参与者的示例变量,这就是参与者的意义所在!
相反,给予参与者一个 * 方法 * 来设置它 * 自己的 * 示例变量。然后你就可以调用这个方法了(用await)。

wfauudbj

wfauudbj2#

不允许使用未在参与者上运行的代码中的属性setter(“参与者隔离代码”是确切的术语)。改变参与者状态的最佳位置是从参与者本身内部的代码。在您的情况下:

actor StatesActor {
    var job1IsActive: Bool = false
    func startJob1() {
        job1IsActive = true
        ...
    }
}
class MyObj {
    let myStates = StatesActor()
    func job1() async {
        await myStates.startJob1()
    }
}

异步属性setter在理论上是可行的,但不安全,这可能就是Swift没有异步属性setter的原因,因为编写if await actor.a == nil { await actor.a = "Something" }这样的代码太容易了,actor.a可以在getter和setter的调用之间改变。
上面的答案在99%的情况下有效但是,在某些情况下,参与者的状态需要从参与者外部的代码进行转换。对于MainActor,请使用MainActor.run(body:)。对于全局参与者,@NameOfActor可应用于函数(并且可以用来定义类似于MainActorrun函数)。在其他情况下,isolated关键字可以用在函数的actor参数之前:

func job1() async {
    await myStates.startJob1()
    let update: (isolated StatesActor) -> Void = { states in
        states.job1IsActive = true
    }
    await update(myStates)
}

相关问题