对SCNNode进行子类化会引发Swift 6的并发问题
我想对SCNNode进行子类化:
open class MyContainer3D: SCNNode {
public init(size: SCNVector3) {
super.init()
self.boundingBox = (min: SCNVector3(0, 0, 0), max: SCNVector3(size.x, size.y, size.z))
self.position = SCNVector3(0, 0, 0)
}
@available(*, unavailable)
public required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
我已将默认隔离域设为主actor,并使用Swift 5+完整并发性检查。
这会带来并发性问题:
主actor隔离的初始化器 'init()' 与非隔离的覆盖声明具有不同的actor隔离性;在Swift 6语言模式下这是一个错误。
不过,如果我这样做,就能工作了:
nonisolated open class MyContainer3D: SCNNode {
@MainActor
public init(size: SCNVector3) {
super.init()
self.boundingBox = (min: SCNVector3(0, 0, 0), max: SCNVector3(size.x, size.y, size.z))
self.position = SCNVector3(0, 0, 0)
}
@available(*, unavailable)
public required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
我的观察:如果把 init?(coder:)(第二个初始化器)标记为主actor,那么将会得到类似的警告:“主actor隔离的初始化器 'init(coder:)' 与非隔离的覆盖声明具有不同的actor隔离性;在Swift 6语言模式下这是一个错误。”
我的问题:
- 为什么
init(size:)与init?(coder:) 的行为不同? - 为什么把
MyContainer3D标记为非隔离并把init(size:)标记为非隔离就能消除这个警告?
解决方案
我找到一个不错的变通方法,可以让SCNNode具备主隔离。我将直接从 MySCNNode 进行子类化,其实现如下:
// MainActor by default from project settings
open class MySCNNode: SCNNode {
// calling super.init() from subclass will call this init which is main isolated,
// since we marked the original nonisolated init() unavailable
public init(_: () = ()) {
// this main isolated init can still call super's non-isolated init
super.init()
}
// Unlike SpriteKit, SCNNode directly inherit from NSObject, which is non-isolated.
// The default generated init is still in main actor, however, overridden init cannot change the isolation of superclass.
// So we manually declare it to be nonisolated. Otherwise will get "Main actor-isolated initializer 'init()' has different actor isolation from nonisolated overridden declaration"
@available(*, unavailable)
nonisolated public override init() {
super.init()
}
@available(*, unavailable)
nonisolated public required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。