I am trying to port SceneKit projects to Swift 6, and I just can't figure out how that's possible. I even start thinking SceneKit and Swift 6 concurrency just don't match together, and SceneKit projects should - hopefully for the time being only - stick to Swift 5.
The SCNSceneRendererDelegate
methods are called in the SceneKit Thread.
If the delegate is a ViewController:
class GameViewController: UIViewController {
let aNode = SCNNode()
func renderer(_ renderer: any SCNSceneRenderer, updateAtTime time: TimeInterval) {
aNode.position.x = 10
}
}
Then the compiler generates the error "Main actor-isolated instance method 'renderer(_:updateAtTime:)' cannot be used to satisfy nonisolated protocol requirement"
Which is fully understandable.
The compiler even tells you those methods can't be used for protocol conformance, unless:
- Conformance is declare as
@preconcurrency SCNSceneRendererDelegate
like this:
class GameViewController: UIViewController, @preconcurrency SCNSceneRendererDelegate {
But that just delays the check to runtime, and therefore, crash in the SceneKit Thread happens at runtime...
Again, fully understandable.
- or the delegate method is declared
nonisolated
like this:
nonisolated func renderer(_ renderer: any SCNSceneRenderer, updateAtTime time: TimeInterval) {
aNode.position.x = 10
}
Which generates the compiler error: "Main actor-isolated property 'position' can not be mutated from a nonisolated context".
Again fully understandable.
If the delegate is not a ViewController but a nonisolated
class, we also have the problem that SCNNode
can't be used.
Nearly 100% of the SCNSceneRendererDelegate
I've seen do use SCNNode or similar MainActor bound types, because they are meant for that.
So, where am I wrong ? What is the solution to use SceneKit SCNSceneRendererDelegate
methods with full Swift 6 compilation ? Is that even possible for now ?