以下代码(为简洁起见进行了简化)会导致崩溃:
Crashed: com.apple.root.user-initiated-qos.cooperative
@Published var thing: Thing?
func start() {
Task { @MainActor in await getThing() }
}
func getThing() async {
self.thing = await foo.fetchThing()
}
根据我的理解,分配
self.thing
是安全完成的,因为它的调用者被分配给主要参与者(从而继承)。这里出了什么问题?
与 GCD 不同,在 Swift 并发中,
getThing
的 actor 隔离取决于 getThing
的声明方式,而不是由 actor 与其调用位置的隔离决定。事实上,您从与主要参与者隔离的任务中调用它这一事实并不重要。如果你想让getThing
跑男主角,你有两个选择:
将
getThing
与主角隔离:
class Foo: ObservableObject
@Published var thing: Thing?
func start() {
Task { await getThing() }
}
@MainActor
func getThing() async {
self.thing = await foo.fetchThing()
}
}
或者,您可以将整个班级与主要演员隔离,这将有效地将
getThing
与主要演员隔离:
@MainActor
class Foo: ObservableObject
@Published var thing: Thing?
func start() {
Task { await getThing() }
}
func getThing() async {
self.thing = await foo.fetchThing()
}
}