Adding Convenience Initializers in Swift Subclass

There are two problems here:

  • SKShapeNode has only one designated initializer: init(). This means that we cannot get out of our initializer without calling init().

  • SKShapeNode has a property path declared as CGPath!. This means that we don’t want to get out of our initializer without somehow initializing the path.

The combination of those two things is the source of the issue. In a nutshell, SKShapeNode is incorrectly written. It has a property path that must be initialized; therefore it should have a designated initializer that sets the path. But it doesn’t (all of its path-setting initializers are convenience initializers). That’s the bug. Putting it another way, the source of the problem is that, convenience or not, the shapeNodeWith... methods are not really initializers at all.

You can, nevertheless, do what you want to do — write a convenience initializer without being forced to write any other initializers — by satisfying both requirements in that order, i.e. by writing it like this:

class MyShapeNode : SKShapeNode {
    convenience init(squareOfSize value: CGFloat) {
        self.init()
        self.init(rectOfSize: CGSizeMake(value, value))
    }
}

It looks illegal, but it isn’t. Once we’ve called self.init(), we’ve satisfied the first requirement, and we are now free to refer to self (we no longer get the “use of ‘self’ in delegating initializer before self.init is called” error) and satisfy the second requirement.

Leave a Comment