Swift 2.0 继承 UIViewController 的子类并调用便利初始化器

Swift 2.0 Subclassing a subclass of UIViewController and called convenience initializers

对于 Swift 2.0/Xcode 7beta3 中 UIViewController 的指定初始化程序和便利初始化程序有些混淆。我们的 UIViewControllers 都是在代码中定义的,没有 Nibs

目前classA是这样继承自UIViewController的

class A : UIViewController {
    convenience init() {
        ...
        self.init(nibName:nil, bundle:nil)
        ...
    }    
}

然后 class B 继承自 class A 并且应该覆盖便利的 init 并将其称为 super.init()

class B : A {
    convenience init() {
        super.init()
        ...
    }    
}

编译器不允许这样做 必须调用超级 class '...' 的指定初始化程序 super.init()[=14] =]

查看文档中的这些图像。
(来源:apple.com


(来源:apple.com

根据图像的方便初始化程序不会被继承。所以如果你想继承你必须使它成为一个指定的初始化器。

class A : UIViewController {
    init() {
        super.init(nibName: nil, bundle: nil)
    }
    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
}

class B : A {
     override init() {
        super.init()
    }
    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
}

此时您可能想知道指定初始化器和便利初始化器之间到底有什么区别?好吧,Convenience 用于在同一个 class 中调用指定的初始化器,你应该用它来做一些设置。

你需要指定你的初始化器,而不是convenience:

class A : UIViewController {
    init() {
        super.init(nibName:nil, bundle:nil)
    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("")
    }
}

class B : A {
    override init() {
        super.init()
    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("")
    }
}

这为您提供了您正在寻找的继承结构。

根据文档

Rule 2 A convenience initializer must call another initializer from the same class.

来自 https://developer.apple.com/library/mac/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html(Initializer Class 类型的委派)

您应该改为调用它自己的初始化程序:

    class B : A {
       convenience init() {
         init()
         ...
       }    
    }

并且 init() 自动继承自它的超类版本

这里是指定初始化器和便利初始化器的通信规则 规则 1: 指定构造器必须从它的直接 superclass.

调用指定构造器

规则 2: 便利初始化器必须从同一个 class.

调用另一个初始化器

规则 3: 便利初始化器最终必须调用指定初始化器。

记住这一点的简单方法是:

指定的初始化程序必须始终向上委托。 便利初始化程序必须始终 委托