2
\$\begingroup\$

I decided to subclass SKSpriteNode for a game test in Swift today and soon realised that it was not as simple as my Objective-C background suggested. After a little hunting around and a bit of testing in Playgrounds I have come up with the following (See below). I have not tested this in a project as I am just starting out on my next game but thought I would add this here to see if I am on the right track with this, does what I have done look right, any suggestions or comments would be most helpful.

I am pretty happy with this, but I was just curious if there was anything I was not doing, or something that I was doing that I should not be.

// ------------------------------------------------------------------- **
// SKSpriteNode subclass, NSCoding not implemented
// ------------------------------------------------------------------- **

class SimpleSprite: SKSpriteNode {
    var simpleName: String
    var simpleType: Double

    init(simpleName: String, simpleType: Double) {
        self.simpleName = simpleName
        self.simpleType = simpleType
        let spriteColor = SKColor.redColor()
        let spriteSize = CGSize(width: 10.0, height: 10.0)
        super.init(texture: nil, color: spriteColor, size: spriteSize)
    }

    required init?(coder aDecoder: NSCoder) {
        // Class does not want to be NSCoding-compatible
        fatalError("init(coder:) has not been implemented")
    }
}

let simpleSprite = SimpleSprite(simpleName: "SimpleRabbit", simpleType: 22.1)
simpleSprite.simpleName
simpleSprite.color

// ------------------------------------------------------------------- **
// SKSpriteNode subclass, NSCoding-compatible
// ------------------------------------------------------------------- **

class CodedSprite: SKSpriteNode {
    var simpleName: String
    var simpleType: Double

    init(simpleName: String, simpleType: Double) {
        self.simpleName = simpleName
        self.simpleType = simpleType
        let spriteColor = SKColor.whiteColor()
        let spriteSize = CGSize(width: 10.0, height: 10.0)
        super.init(texture: nil, color: spriteColor, size: spriteSize)
    }

    required init?(coder aDecoder: NSCoder) {
        self.simpleName = aDecoder.decodeObjectForKey("SIMPLE_NAME") as String
        self.simpleType = aDecoder.decodeDoubleForKey("SIMPLE_TYPE")
        super.init(coder: aDecoder)
    }

    override func encodeWithCoder(aCoder: NSCoder) {
        aCoder.encodeObject(self.simpleName, forKey: "SIMPLE_NAME")
        aCoder.encodeDouble(self.simpleType, forKey: "SIMPLE_TYPE")
        super.encodeWithCoder(aCoder)
    }

}

let codedSprite = CodedSprite(simpleName: "CodedRabbit", simpleType: 22.1)
codedSprite.simpleName
codedSprite.color
\$\endgroup\$

1 Answer 1

4
\$\begingroup\$

I'm going to ignore the non-coded class. I'm not sure why you'd include both of these.

With that said, here are some things I noticed about the coded class.


Rather than init(simpleName:simpleType:), why don't we expand on our super class's init and also accept the arguments our super class's init takes:

init(texture: SKTexture?, color: UIColor, size: CGSize, name: String, type: Double) {
    self.simpleName = name
    self.simpleType = type
    super.init(texture: texture, color: color, size: size)
}

Then, if we want an initializer that takes just some of these values and uses defaults for the rest, we should make convenience initializers:

convenience init(name: String, type: Double) {
    self.init(texture: nil, color: UIColor.whiteColor(), size: CGSizeMake(10.0, 10.0), name: name, type: type)
}

And we probably should override any of SKNode's constructors which we intend to keep available:

override convenience init(texture: SKTexture?, color: UIColor, size: CGSize) {
    self.init(texture: texture, color: color, size: size, name: "", type: 0.0)
}

Ultimately, the point is, all of our initialization logic should go in as few constructors as possible. All of our other constructors should call these few designated constructors.

\$\endgroup\$
3
  • \$\begingroup\$ Hiya, thank you for the comments, very much appreciated. The inclusion of the non-coded class was just to show how the non-coded version would look as thats probably the version most people will end up using. \$\endgroup\$
    – fuzzygoat
    Commented Nov 26, 2014 at 13:08
  • \$\begingroup\$ I'm not sure why you'd use a non-coding compliant version of anything when a coding-compliant version is available. The coding methods don't get in the way of normal usage. I wouldn't make the non-coding version available. \$\endgroup\$
    – nhgrif
    Commented Nov 26, 2014 at 18:52
  • \$\begingroup\$ @fuzzygoat I agree with nhgrif, do not bother with non-coded versions. You will not be able to use these inside of the SpriteKit Scene builder and that may start consing people \$\endgroup\$ Commented Jul 8, 2016 at 17:36

Not the answer you're looking for? Browse other questions tagged or ask your own question.