为什么我必须为我的程序设计UIViewController子类继续声明相同的必需但未实现init(coder aDecoder)的初始化程序?

时间:2015-08-06 22:38:29

标签: ios swift uiviewcontroller designated-initializer

也许这只是我,但我发现迅速的某些方面......至少可以说是钝的。

我大部分时间都不使用Interface Builder,因为我喜欢使用PureLayout。所以我希望创建一个UIViewController子类,比如PureViewController,它有一个方便的init没有参数:

class PureViewController : UIViewController {

    init() {
        super.init(nibName: nil, bundle: nil)
    }

}

但这并不合适,因为XCode告诉我,我还必须实现init(coder aDecoder: NSCoder)。好的,没关系!这就是我创建这个类的原因 - 所以我不必再为子类做这个。

class PureViewController : UIViewController {

    init() {
        super.init(nibName: nil, bundle: nil)
    }

    required init(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}

好的,现在这就是我没有得到的。

我使用初始化程序SomePureViewController : PureViewController ...

定义了一个子类init(viewModel:ICrackersViewModel)
class SomePureViewController : PureViewController {

    init(viewModel:ICrackersViewModel) {
        super.init()
    }

}

STILL 希望我定义同样的愚蠢初始化程序,直到王国来临!

class SomePureViewController : PureViewController {

    init(viewModel:ICrackersViewModel) {
        super.init()
    }

    required init(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}

现在我理解了这个想法 - 我的子类中没有init(decoder),即使它是在其父类中定义的。

也许我总是用UIViewController处理这个问题,之前从未注意过。

我的问题如下:

  1. 我做错了会导致这种行为吗?
  2. 在继承之外有什么方法可以避免重复我自己吗?
  3. 是否有计划改变这个计划?

3 个答案:

答案 0 :(得分:2)

关键是可以通过了解基类型来初始化可能派生的类。

让我们假设一个基类

class Base {
    let value: Int

    required init(value: Int) {
        self.value = value
    }
}

和一个功能

func instantiateWith5(cls: Base.Type) -> Base {
    return cls.init(value: 5)
}

然后我们可以做

let object = instantiateWith5(Base.self)

现在,如果有人定义派生类

class Derived: Base {
    let otherValue: Int

    init() {
        otherValue = 1
        super.init(value: 1)
    }

    required init(value: Int) {
        fatalError("init(value:) has not been implemented")
    }
}

我们至少可以致电

let object2 = instantiateWith5(Derived.self)

违反了LSP,但这是你的代码问题,而不是语言。

Swift必须保证初始化器将对象保持在初始化状态,即使它们是从基础对象派生的,所以我想改变它会是一件坏事。如果您想定义一个不可反序列化并因此违反LSP的UIViewController,那么这是您的决定 - 但不要指望该语言在此支持您。

答案 1 :(得分:1)

我认为这是一个很快的问题,如何避免这种情况。我们都讨厌这个空的致命错误初始化器。

答案 2 :(得分:1)

由于初始化程序标有required关键字,因此所有子类都必须实现该初始化程序,并且还必须在其实现上指定required,以便子类也是必需的实现它。

  

必需的初始化程序

     

在之前写下所需的修饰符   类初始值设定项的定义,用于指示每个子类   该类必须实现该初始化程序

     

您还必须在所需初始化程序的每个子类实现之前编写必需的修饰符,以指示初始化程序要求适用于链中的其他子类。“

自1.0以来,它一直是Swift语言的一部分,不太可能改变。

问题实际上与在UIViewController类定义中使用required关键字有关。理论上这可以改变,但我认为这不太可能。