Wil*_*ler 20 swift swift-concurrency
我想要某种使用 同步的全局变量@MainActor。
这是一个示例结构:
@MainActor
struct Foo {}
Run Code Online (Sandbox Code Playgroud)
我想要一个像这样的全局变量:
let foo = Foo()
Run Code Online (Sandbox Code Playgroud)
但是,这不会编译并出现错误Call to main actor-isolated initializer 'init()' in a synchronous nonisolated context。
很公平。我尝试在主线程上构建它,如下所示:
let foo = Foo()
Run Code Online (Sandbox Code Playgroud)
这可以编译!但是,它会崩溃EXC_BAD_INSTRUCTION,因为DispatchQueue.main.sync无法在主线程上运行。
我还尝试创建一个包装函数,例如:
let foo = DispatchQueue.main.sync {
Foo()
}
Run Code Online (Sandbox Code Playgroud)
并使用
let foo = syncMain {
Foo()
}
Run Code Online (Sandbox Code Playgroud)
但编译器无法识别if Thread.isMainThread并再次抛出相同的错误消息Call to main actor-isolated initializer 'init()' in a synchronous nonisolated context。
这样做的正确方法是什么?我需要某种可以在应用程序启动之前初始化的全局变量。
Bra*_*key 19
一种方法是将变量存储在容器中(就像充当enum抽象命名空间)并将其与主要参与者隔离。
@MainActor
enum Globals {
static var foo = Foo()
}
Run Code Online (Sandbox Code Playgroud)
一种同样有效的方法是static在对象本身上具有“类单例”属性,该属性具有相同的目的,但没有附加对象。
@MainActor
struct Foo {
static var shared = Foo()
}
Run Code Online (Sandbox Code Playgroud)
您现在可以通过 访问全局对象Foo.global。
需要注意的一件事是,现在将延迟初始化(在第一次调用时)而不是立即初始化。但是,您可以通过对对象进行任何访问来强制尽早进行初始化。
// somewhere early on
_ = Foo.shared
Run Code Online (Sandbox Code Playgroud)
@MainActor不会static let在主线程上初始化变量。static var代替使用。
@MainActor
struct Foo {
static let shared = Foo()
init() {
print("foo init is main", Thread.isMainThread)
}
func fooCall() {
print("foo call is main", Thread.isMainThread)
}
}
Run Code Online (Sandbox Code Playgroud)
Task.detached {
await Foo.shared.fooCall()
}
// prints:
// foo init is main false
// foo call is main true
Run Code Online (Sandbox Code Playgroud)
这是一个错误(请参阅问题58270),已在 Swift 5.10 中修复。
| 归档时间: |
|
| 查看次数: |
13612 次 |
| 最近记录: |