gpt4 book ai didi

swift - 如何使用@MainActor 初始化全局变量?

转载 作者:行者123 更新时间:2023-12-04 14:49:36 26 4
gpt4 key购买 nike

我想要某种使用 @MainActor 同步的全局变量.
这是一个示例结构:

@MainActor
struct Foo {}
我想要一个像这样的全局变量:
let foo = Foo()
但是,这不会编译并出错 Call to main actor-isolated initializer 'init()' in a synchronous nonisolated context .
很公平。我试图在主线程上构建它,如下所示:
let foo = DispatchQueue.main.sync {
Foo()
}
这编译!但是,它崩溃了 EXC_BAD_INSTRUCTION , 因为 DispatchQueue.main.sync不能在主线程上运行。
我还尝试创建一个包装函数,如:
func syncMain<T>(_ closure: () -> T) -> T {
if Thread.isMainThread {
return closure()
} else {
return DispatchQueue.main.sync(execute: closure)
}
}
并使用
let foo = syncMain {
Foo()
}
但是编译器不识别 if Thread.isMainThread并再次抛出相同的错误消息, Call to main actor-isolated initializer 'init()' in a synchronous nonisolated context .
这样做的正确方法是什么?我需要某种可以在应用程序启动之前初始化的全局变量。

最佳答案

一种方法是将变量存储在容器中(如 enum 充当抽象命名空间)并将其与主要参与者隔离。

@MainActor
enum Globals {
static let foo = Foo()
}
同样有效的方法是使用“类似单例”的 static对象本身的属性,用于相同的目的,但没有附加对象。
@MainActor
struct Foo {
static let global = Foo()
}
您现在可以通过 Foo.global 访问全局对象.
需要注意的一点是,这现在将被延迟初始化(在第一次调用时)而不是立即初始化。
但是,您可以通过对对象进行任何访问来强制初始化。
// somewhere early on
_ = Foo.global

警告
TL;DR:@MainActor 在 Swift 5.5 中被破坏,不会在主线程上调用一些东西。这对您来说可能是也可能不是问题。
虽然这可以编译和工作,但似乎这可能会调用主线程之外的初始化程序,随后在初始化程序内部进行的任何调用。
@MainActor
struct Bar {
init() {
print("bar init is main", Thread.isMainThread)
}
func barCall() {
print("bar call is main", Thread.isMainThread)
}
}


@MainActor
struct Foo {
@MainActor
static let global = Foo()

init() {
print("foo init is main", Thread.isMainThread)
let b = Bar()
b.barCall()
}

func fooCall() {
print("foo call is main", Thread.isMainThread)
}
}
Task.detached {
await Foo.global.fooCall()
}
// prints:
// foo init is main false
// bar init is main false
// bar call is main false
// foo call is main true
我不确定这是错误还是预期的行为,但对我来说似乎不正确(请参阅 SR-15227 )。
解决方法是始终确保在 @MainActor 中进行初始化。上下文,我们可以通过注释我们第一次调用的闭包来实现。
Task.detached { @MainActor in
await Foo.global.fooCall()
}

关于swift - 如何使用@MainActor 初始化全局变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69263941/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com