Choc13 Choc13 - 5 months ago 18
Swift Question

SpriteBuilder Swift code connections nil reference and deallocation issues

I am using Swift (XCode 7.2.1) and SpriteBuilder (1.4.9) to create a game. However I am having some problems with the creating code connections between CCB files and Swift classes. I followed the tutorials online and added a doc root var code connection name in SpriteBuilder and then set up the corresponding property in the class as a

private weak var m_myVar: MyClass!
. However whenever I try and access the property I get a
nil
reference. If I remove the
weak
attribute from the code connection then I can access the property, but I receive deallocation issues when the scene is detroyed, e.g. navigating to a new scene using the
CCDirector.shareDirector().replaceScene()
method.

In my specific case I have a
MainScene
in SpriteBuilder with the following node hierarchy within it:
CCNode
->
CCNodeGradient
->
Tile
. Where
Tile
a subclass of
CCNode
defined in a different CCB file and has the
doc root var
code connection name of
m_levelLabel
, which maps to the
private weak var m_levelLabel: Tile!
property of the
MainScene
class.

The
Tile
class has 2 properties
m_background
of type
CCSprite9Slice
and
m_label
of type
CCLabelTTF
, both of which are mapped to
private weak var
properties in the
Tile
Swift class.

When the
MainScene
loads I attempt to set some properties on the
m_levelLabel
using the following code:

internal func didLoadFromCCB() {
m_levelLabel.setValue("2");
}


and
Tile.setValue
is defined in the
Tile
class as:

internal func setValue(value: String) {
m_label.string = value;
}


But when the
setValue
method executes the
m_label
property is
nil
and so the
fatal error: unexpectedly found nil while unwrapping an Optional value
occurs. This is odd as clearly my code connections in the
MainScene
class have worked fine as I was able to call
m_levelLabel.setValue
.

Interestingly if I change the properties in the
Tile
class to be defined as strong references like:

private var m_label: CCLabelTTF!;


Then the code executes fine and the value of the label is updated when the
MainScene
loads. However the app now crashes when I try and navigate away from the
MainScene
with the error
malloc: *** error for object 0x7a9f3200: pointer being freed was not allocated
which sounds like there is a problem when destroying the, now, strong properties in the
Tile
class owned by the
MainScene
.

What could be going on here? What is the correct way to define code connections in Swift? Note I receive no warnings in the console about missing code connection properties.

For reference here is the
MainScene
and
Tile
class in their entirety:

Main.swift

import Foundation

internal class MainScene: CCScene {

internal func didLoadFromCCB() {
m_levelLabel.setValue("1");
m_progressLabel.setValue("0%");
}

internal func play() {
let gameplayScene: CCScene = CCBReader.loadAsScene("Gameplay/GameplayScene");
CCDirector.sharedDirector().replaceScene(gameplayScene);
}

internal func levelSelection() {
print("Pressed level selection");
}

internal func progress() {
print("Pressed progress button");
}

private weak var m_playButton: CCButton!;
private weak var m_levelSelectionButton: CCButton!;
private weak var m_progressButton: CCButton!;
private weak var m_levelLabel: Tile!;
private weak var m_progressLabel: Tile!;
}


Tile.swift

import Foundation

internal class Tile : CCNode {

internal var value: String? {
return m_label?.string;
}

internal func setValue(value: String) {
m_label.string = value;
}

private weak var m_label: CCLabelTTF!;
private weak var m_background: CCSprite9Slice!;
}

Answer

So it turns out that for the code connections to always work they must have internal accessibility rather than private. E.g.

internal weak var m_label: CCLabelTTF!;

rather than

private weak var m_label: CCLabelTTF!;

I'm not sure why private works in some instances, but not in others and it's a shame that I can't properly encapsulate this data. I guess this is either due to a bug in the SpriteBuilder library or a limitation due to the Swift language.

Comments