6

I'm very new to iOS development, but I've been playing around with the SpriteKit template app to learn how things work and try to boot up on Swift while I'm at it. One thing I'm having trouble with is how to work with SpriteKit subclasses.

I'm in the GameScene.swift file and I'm trying to extract a class for the "Hello World" label, so here's what that file looks like:

//  GameScene.swift

import SpriteKit

class HelloLabel: SKLabelNode {
    init(fontNamed: String) {
        super.init(fontNamed: fontNamed)
        self.text = "Hello, World!"
        self.fontSize = 65;
        self.position = CGPoint(x: 400, y: 500);
    }
}

class GameScene: SKScene {
    override func didMoveToView(view: SKView) {
        /* Setup your scene here */
//        let myLabel = SKLabelNode(fontNamed:"Chalkduster")
//        myLabel.text = "Hello, World!";
//        myLabel.fontSize = 65;
//        myLabel.position = CGPoint(x: 400, y: 500);

        let myLabel = HelloLabel(fontNamed: "Chalkduster")
        self.addChild(myLabel)
    }

    override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
        /* snip, no changes made here */
    }

    override func update(currentTime: CFTimeInterval) {
        /* snip, no changes made here */
    }
}

So, HelloLabel is intended to just be a pass-through in an attempt to understand how everything wires together, but when I run the app, I get the following error:

/Users/jon/Projects/ErrorExample/ErrorExample/GameScene.swift: 11: 11: fatal error: use of unimplemented initializer 'init()' for class 'ErrorExample.HelloLabel'

I'm not understanding what this message is trying to tell me. The way I read this error is that its complaining that I haven't implemented an initializer called init in the class ErrorExample.HelloLabel, but it sure looks like I have to me!

So, what am I doing wrong here - how does one extract a class to hide all this setup?

jonallured
  • 63
  • 1
  • 4

4 Answers4

11

I'm not certain exactly why, but the hidden functionality inside SKLabelNode was trying to call an init function with no parameters. This seems to work:

class HelloLabel: SKLabelNode {
    init() {
        super.init()
    }

    init(fontNamed fontName: String!) {
        super.init(fontNamed: fontName)
        self.text = "Hello, World!"
        self.fontSize = 65;
        self.position = CGPoint(x: 400, y: 500);
    }
}
Dash
  • 17,188
  • 6
  • 48
  • 49
2

This seems to work better:

class LinkLabel: SKLabelNode {

    override init() {
        super.init()
    }

    override init(fontNamed fontName: String!) {
        super.init(fontNamed: fontName)
        self.text = "Hello, World!"
        self.fontSize = 65;
        self.position = CGPoint(x: 400, y: 500);
    }

    required init(coder aDecoder: NSCoder!) {
        super.init()
    }

}
zeeple
  • 5,509
  • 12
  • 43
  • 71
0

Perhaps since the superclass expects an NSString* changing init(fontNamed: String) { to init(fontNamed: NSString) { will resolve the issue?

Or another possibility could by using the obj-c bridging:

init(fontNamed: String) {
    super.init(fontNamed: fontNamed.bridgeToObjectiveC())
    ...
}
Jiaaro
  • 74,485
  • 42
  • 169
  • 190
  • Thanks Jiaaro, but when I add that keyword, then I get this error: 'override' is not valid on this declaration. – jonallured Jun 06 '14 at 15:09
  • oh you are 100% right - init doesn't require `override` – Jiaaro Jun 06 '14 at 15:53
  • @jonallured ok maybe it's a type thing - since the type of the argument is a `String` and the superclass expects an `NSString*` – Jiaaro Jun 06 '14 at 16:22
-1

You have to do first your class initialization and after that initialize superclass. So your init() should look like this:

init(fontNamed: String) {
        self.text = "Hello, World!"
        self.fontSize = 65;
        self.position = CGPoint(x: 400, y: 500);
        super.init(fontNamed: fontNamed)
    }

It's due to safety and was explained in session 403 of WWDC, Intermediate Swift.

cojoj
  • 6,405
  • 4
  • 30
  • 52
  • 1
    Thanks Cojoj, but this doesn't work because you'll get an error that you've used `text` before you called `init`. You have to `super.init` first. – jonallured Jun 07 '14 at 17:32