3

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.

jaxreiff
  • 503
  • 1
  • 4
  • 14
  • Can you show us how you declare your camera in the first case please ? – H4Hugo Jun 22 '16 at 09:05
  • This is it, I assumed that the `camera` optional variable in the SKScene (`self` here refers to an SKScene subclass) could be initialized and that reference would protect the camera object from garbage collection. `self.camera` is declared in SKScene files within SpriteKit. – jaxreiff Jun 22 '16 at 09:11

1 Answers1

3

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).

Community
  • 1
  • 1
Hamish
  • 78,605
  • 19
  • 187
  • 280