In the following code:
public class Foo {
public func createNode() -> SCNNode {
return SCNNode()
}
public func createNode() -> SKNode {
return SKNode()
}
}
Compiling with Swift 6 strict concurrency checking, the line return SKNode()
doesn't compile with the error Call to main actor-isolated initializer 'init()' in a synchronous nonisolated context
and the proposed fix Add '@MainActor' to make instance method 'createNode()' part of global actor 'MainActor'
.
Any call to a SKNode method or property does the same.
This doesn't happen with the return SCNNode()
.
In my app, these methods should be called inside my SCNSceneRendererDelegate
methods, such as renderer(_:updateAtTime:)
, so I can't take the penalty of going back to the MainActor.
Why is SKNode bound to MainActor (when SCNNode is not), and how to walk this around ?
SKNode
is a subclass of UIResponder
, and UIResponder
is isolated to the main actor, so SKNode
is, too.
Also see Getting Started with Nodes: Ensure Node Access on the Main Thread. They are explicit that you must do this on the main thread (justifying the isolation to the main actor).
To resolve this, you can probably solve this by isolating createNode
to the main actor, e.g.,
@MainActor
public func createNode() -> SKNode {…}
And, because SKNode
is not Sendable
, this createNode
must be called from a context that is also isolated to the main actor, too. Or, if Foo
warrants it, perhaps isolate the whole type to the main actor, too. It’s hard to be specific without seeing more of the Foo
implementation, how you’re ensuring the thread-safety of that, etc. But hopefully this is enough to get you going.