I'm pouring over the Swift documentation about initializers and unwrapping and I'm failing to grok something fundamental about the way this works.
Goal: I'd like to subclass SKShapeNode
and use let reverse : Bool
to define an instance variable that gets set only in the constructor and never need to be modified. That seems to be the correct way of defining such variables, but this blows up in the following code.
The following code works, i.e., it compiles, doesn't crash and gets me the desired behavior.
public class BeamedNotesNode: SKShapeNode {
var notes : [Note]!
var noteNodes : [NoteNode]?
var beam : BeamNode?
var childBeams : [BeamNode]?
var reverse : Bool?
convenience public init(
withTicks notes: [Note],
reverse: Bool = false)
{
self.init(rect: CGRect(x: 0, y: 0, width: 1, height: 1))
self.notes = notes
self.reverse = reverse
...
However, when I modify it to use let reverse : Bool
, I get the error: Class 'BeamedNotesNode' has no initializers
at compile time:
public class BeamedNotesNode: SKShapeNode {
var notes : [Note]!
var noteNodes : [NoteNode]?
var beam : BeamNode?
var childBeams : [BeamNode]?
let reverse : Bool
convenience public init(
withTicks notes: [Note],
reverse: Bool = false)
{
self.init(rect: CGRect(x: 0, y: 0, width: 1, height: 1))
self.notes = notes
self.reverse = reverse
...
It seems like I should be able to use let
and avoid an ugly force-unwrapped instance variable. How do I achieve that here?
The problem is that if you have a non-optional constant, you need to make sure it's initialized by the designated initializer, too.
The easiest solution if you want it to behave like a non-optional constant is to (a) provide a default value for the variable; but (b) make the setter
private
, i.e.I know this isn’t quite what you are looking for, but externally it behaves like a constant, but your convenience initializer can still override the value with whatever was supplied as a parameter.