Search code examples
iosswiftsprite-kitoption-typeskscene

SpriteKit SKCameraNode - Nil when unwrapping an optional value just after assigned


I'm using SpriteKit in an iOS app, and trying to initialize the camera property of my SKScene in the overridden didMoveToView method. If I just initialize it like so:

override func didMoveToView(view: SKView) {
    ...
    self.camera = SKCameraNode()
    self.addChild(self.camera!)
}

...it throws the exception unexpectedly found nil while unwrapping an Optional value at the self.addChild line, but if I do this:

override func didMoveToView(view: SKView) {
    ...
    let camera = SKCameraNode()
    self.camera = camera
    self.addChild(self.camera!)
}

...it works fine, no exception. Why are these two ways different? Is there some kind of garbage collection happening? Its not inconvenient to use the second format, that works, but I'm curious what differs that I'm missing.


Solution

  • The camera property of SKScene is defined as weak:

    weak public var camera: SKCameraNode?
    

    Therefore, as ARC will deallocate any instance that doesn't have a strong reference to it (Swift uses ARC, not garbage collection) – as soon as you assign SKCameraNode() to it, it will be deallocated and therefore will be nil. You then proceed to force unwrap it (which you should always avoid doing), causing the crash.

    Your second example works as you have a strong reference to your camera instance through your

    let camera = SKCameraNode()
    

    declaration, therefore preventing it from being deallocated while that strong reference to it exists (note that addChild will also create a strong reference to it).