@MainActor
class A {}
class VC: UIViewController {
let foo: A
init() {
self.foo = A() // Error: Call to main actor-isolated initializer 'init()' in a synchronous nonisolated context
super.init(nibName: nil, bundle: nil)
}
@MainActor
init() {
self.foo = A() // Compiles
super.init(nibName: nil, bundle: nil)
}
init(_ void: Void = ()) {
self.foo = A() // Compiles
super.init(nibName: nil, bundle: nil)
}
}
我知道
A()
应该在主要参与者初始化器上调用,但为什么第一个初始化器不从 @MainActor
继承
UIViewController
?为什么 Void
参数消除了错误(即使使用 -warn-concurrency
)?
注意:如果我用
VC
注释 @MainActor
,我会在第一个初始化器中得到与 super.init
相同的错误,而第三个初始化器仍然有效。
@MainActor
限制所有方法和属性可从 A 类的主线程进行访问。
let foo: A
不是类 A,它是存储对类 A 的引用的实例,您没有采取任何措施来使设置 foo 线程安全。 init
的其中一个 VC
设置为仅在设置 foo 的主线程中执行,但另一个可以由任何线程调用并设置 foo。
编辑:我认为您可能会发现有用的更多信息 如果您的唯一目标是线程安全,那么使用 MainActor 不是一个好方法,这意味着只有与 GUI 交互相关的线程才能访问您的类,这可能会阻止某些必须在主线程中运行的实际代码执行,因为线程安全你可能更好地使用参与者,它们像类一样工作,但一次只能有一个线程在其中,它们可以是任何线程,并且不同的方法可以由不同的线程在不同的时间访问,但只有一个会一次只是演员。
您还可以通过添加初始化器并标记它来解决问题
nonisolated
。
@MainActor
class A {
nonisolated init() {}
func load() async -> String {
return "Async!"
}
}
我的问题是我没有在视图中包含@MainActor,但在底层 Store/State 上注释了宏