我很好奇,有人可以帮我处理 swift 6 错误吗?考虑这段代码:
class Foo {
init() async throws {}
}
struct ContentView: View {
var body: some View {
Button ("Test") {
Task {
let _ = try await Foo()
}
}
}
}
如果项目的 Swift 语言版本设置为“Swift 6”(Xcode 16.0),则
let _ = ...
行会给出以下错误:
对非隔离函数隐式异步调用返回的不可发送类型“Foo”不能跨越参与者边界。
这是怎么回事?我已经知道如何使 Foo 可发送 - 这不是我正在寻找的。相反,我试图了解演员的情况。
我相信
Task
闭包将在@MainActor
上运行。不知何故,异步初始化程序似乎导致我的 Foo
对象跨越参与者边界,但我不明白为什么。它可能与错误中引用的隐式调用有关。但这个隐式调用到底是什么?有人能给我指出一些解释这种情况的文档吗?
顺便说一句,我知道使任务分离可以解决这个问题。但我还是不明白到底发生了什么。
你说:
我相信
闭包将在Task
上运行。@MainActor
是的,
Task
与主要演员隔离。
但是
Foo
的初始化器不是。它是一个异步初始化程序,不与任何特定参与者隔离,因此它将在“通用执行程序”上运行。在MainActor.preconditionIsolated()
的初始化器中添加一个Foo
,你会发现它不在主角身上。这就是问题的根源,该对象正在协作线程池中的任意线程上初始化,并被发送回主要参与者,如果 Foo
不是 Sendable
,则无法执行此操作。