NJanf
NJanf

Reputation: 359

Swift: Property not initialized at super.init call

I am making a little custom keyboard and I have a set of variables inside the class that need to be initialized inside the 'override init()' as can be seen below:

class KeyboardViewController: UIInputViewController {

var button01: CharacterButton
var button02: CharacterButton
...

and

override init()   {

        //Initialize buttons and assign attributes
        button01 = CharacterButton.createButton("Q", labelOfButton: "Q")
        button02 = CharacterButton.createButton("W‎", labelOfButton: "W")

        super.init()
}

In addition to that I have also added the following code, as it is apparently required since Xcode 6 beta 5:

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

But that last snippet of code results in an error saying:

Property 'self.button01' not initialized at super.init call

Why would this happen when I have already initialized 'button01' and called the 'super.init()' inside the former 'override init()' function? This is driving me nuts.

Upvotes: 10

Views: 11701

Answers (3)

Ivica M.
Ivica M.

Reputation: 4823

init(coder:) and init() are two different designated initialisers. You have few options here. The best one would be to initialise your properties in-place.

class KeyboardViewController: UIInputViewController {

    var button01 = CharacterButton.createButton("Q", labelOfButton: "Q")
    var button02  = CharacterButton.createButton("W‎", labelOfButton: "W")
}

EDIT:

Removed initializers from the above code. If all the properties are initialised in-place, there is no need for overriding any initializer. All of them will simply be inherited automatically (including init(coder:)).


Or you can do something like this, if your class is never going to be created from nibs (including storyboards:

    class KeyboardViewController: UIInputViewController {

    ...

    required init(coder aDecoder: NSCoder!) {
        fatalError("This class doesn't support NSCoding.")
    }
}

I don't like this solution, as it breaks the superclass' promise about implementing NSCoding, but it 'works'. Finally, you can make your properties be implicitly unwrapped optionals.

class KeyboardViewController: UIInputViewController {

    var button01: CharacterButton!
    var button02: CharacterButton!

    ...
}

But if you do that, your init(coder:) will become unsafe, so it's better to throw fatalError from there and stick to non-optionals.

Upvotes: 8

Luca Angeletti
Luca Angeletti

Reputation: 59506

This happens because if the class is created with the second initializer

init(coder aDecoder: NSCoder!)

then your variables button01 and button02 are never initialized. And since they are not optionals, the compiler does not allow this.

You could change the second initializer to something like this:

required init(coder aDecoder: NSCoder!) {
    button01 = CharacterButton.createButton("Q", labelOfButton: "Q")
    button02 = CharacterButton.createButton("W‎", labelOfButton: "W")
    super.init(coder: aDecoder)
}

Or you could initialize you variables when they are declared:

var button01 = CharacterButton.createButton("Q", labelOfButton: "Q")
var button02 = CharacterButton.createButton("W‎", labelOfButton: "W")

Upvotes: 4

Chris Wagner
Chris Wagner

Reputation: 21003

If you're not interested in implementing init(coder:) you should throw an error.

required init(coder aDecoder: NSCoder!) {
    fatalError("use init() method")
}

I am not sure if the system invokes init(coder:) for UIInputViewController sub-classes however.

Upvotes: 0

Related Questions