从无任务上下文同步访问actor属性



actors与现有代码集成似乎并不像苹果希望你相信的那么简单。考虑以下简单的参与者:

actor Foo {
var value: Int = 0
}

尝试从任何AppKit/UIKit(无任务(控制器访问此属性都无法工作,因为每个Task都是异步的。

class AppKitController {
func myTaskLessFunc() {
let f = Foo()
var v: Int = -1
Task { v = await f.value }
}
}

这将给您带来预期的错误Mutation of captured var 'v' in concurrently-executing code,如果您试图锁定它,它也不会起作用。nonisolatedactor方法也没有帮助,因为您会遇到同样的问题。

那么,如何在无任务上下文中同步读取actor属性呢?

我找到了一种使用Combine的方法,如下所示:

import Combine
actor Foo {
nonisolated let valuePublisher = CurrentValueSubject<Int, Never>(0)
var value: Int = 0 {
didSet {
valuePublisher.value = value
}
}
}

通过提供一个非隔离的发布者,我们可以将actor值安全地传播到外部,因为Publisher是线程安全的。

调用方可以访问foo.valuePublisher.value,也可以从外部订阅它,而不需要异步上下文。

最新更新