Swift:在调用super.init时属性未被初始化

10

我正在制作一个小型自定义键盘,我在类内部有一组变量,需要在“override init()”函数中进行初始化,如下所示:

class KeyboardViewController: UIInputViewController {

var button01: CharacterButton
var button02: CharacterButton
...

并且
override init()   {

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

        super.init()
}

除此之外,我还添加了以下代码,因为它显然是自Xcode 6 beta 5以来所必需的:
required init(coder aDecoder: NSCoder!) {
    super.init(coder: aDecoder)
}

但是最后一段代码会导致一个错误,错误信息为:

在调用super.init时,未初始化属性'self.button01'

当我已经在之前的“override init()”函数中初始化了'button01'并调用了'super.init()',为什么会出现这种情况?这让我很困扰。

尝试在你的 button01... 代码之前调用 super.init()。 - André Muniz
1
我不能这样做,否则会出现另一个错误,提示“在super.init调用时self.button01未初始化”,基本上是说我必须先初始化按钮,然后再像我在原帖中所做的那样调用super.init()。 - NJanf
3个回答

8

init(coder:)init()是两个不同的指定初始化器。在这里你有几个选择。最好的方法是直接在原地初始化你的属性。

class KeyboardViewController: UIInputViewController {

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

编辑:

从上面的代码中删除了初始化程序。如果所有属性都在原地初始化,那么就不需要覆盖任何初始化程序。它们都将自动继承(包括init(coder:))。


或者,如果您的类永远不会从nib文件(包括storyboards)中创建,则可以执行以下操作:

    class KeyboardViewController: UIInputViewController {

    ...

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

我不喜欢这个解决方案,因为它破坏了超类有关实现 NSCoding 的承诺,但是它“可以工作”。最后,你可以将你的属性设置为隐式解包可选项。

class KeyboardViewController: UIInputViewController {

    var button01: CharacterButton!
    var button02: CharacterButton!

    ...
}

但是如果您这样做,您的init(coder:)将变得不安全,因此最好从那里抛出fatalError并坚持使用非可选项。


4
这是因为如果使用第二个初始化程序创建类。
init(coder aDecoder: NSCoder!)

如果你的变量button01和button02没有初始化,它们不是可选类型,那么编译器将不允许这种情况发生。

你可以更改第二个初始化值,例如:

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

或者你可以在声明变量时进行初始化:

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

0

如果您不想实现init(coder:),则应抛出错误。

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

我不确定系统是否会为UIInputViewController的子类调用init(coder:)方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接