Swift UINavigationController子类中的强制init覆盖

Mar*_*tin 6 overriding swift

我目前正在UINavigationController为一个为视图控制器流提供服务的框架进行子类化(在某种程度上,就像UIImagePickerController这样)

这是我的实现示例,简化为尽可能简单,可以在游乐场中运行.

import UIKit

public class MyNavigationController: UINavigationController {

    public var anyVar: Int?

    public init(anyVar: Int) {
        let viewController = UIViewController()
        super.init(rootViewController: viewController)

        self.anyVar = anyVar
    }

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

let navigationController = MyNavigationController(anyVar: 42)
Run Code Online (Sandbox Code Playgroud)

最后一行是崩溃,有一个EXC_BAD_INSTRUCTION.当我在Xcode中运行,它告诉我,在运行时init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)失踪了.

如果我覆盖该方法:

public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
Run Code Online (Sandbox Code Playgroud)

......一切运作良好:您可以尝试自己的游乐场.

我不明白为什么.这对我来说听起来不合逻辑.

UIViewController文件说:

如果您是UIViewController的子类,则必须调用此方法的超级实现,即使您没有使用NIB也是如此.(为方便起见,默认的init方法将为您执行此操作,并为这两个方法参数指定nil.)

但是init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)super.init(rootViewController: viewController)初始化开始调用我的覆盖!
如果没有覆盖它,我想init(nibName:bundle:)应该调用UIViewController ,但不是.

我仍然无法理解为什么重写方法和调用super使程序更好地工作.IMO,覆盖一个方法,而只调用super.thisMethod是完全没用的,它只在调用堆栈中添加一个方法调用.

我必须遗漏一些关于Swift init方法的要点,但我无法弄清楚是什么.

小智 6

之所以发生这种情况,是因为Swift如何继承初始化程序。如果您在当前类中未声明任何初始化器,则编译器将从父类继承所有初始化器。但是,如果您覆盖/添加了新的初始化程序(并使用来完成init(anyVar:)),Swift不会自动从父类继承初始化程序,因此无法从子类访问它们,这会导致运行时崩溃。

如果您有兴趣的原因超出了这个行为,你可以检查出中级斯威夫特部分和WWDC 2014(地方约34分钟的标志,他们正在谈论初始化继承)