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
    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
    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\$ Jul 8, 2016 at 17:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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