我目前正在为服务 View Controller 流的框架子类化 UINavigationController
(在某种程度上,就像 UIImagePickerController
那样)
这是我的实现示例,已尽可能简化,可以在 Playground 上运行。
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)
最后一行崩溃,出现 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)
}
...一切正常:您可以尝试使用自己的 Playground 。
我不明白为什么。这对我来说听起来不合逻辑。
UIViewController
文档说:
If you subclass UIViewController, you must call the super implementation of this method, even if you aren't using a NIB. (As a convenience, the default init method will do this for you, and specify nil for both of this methods arguments.)
但是我的 init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)
override 被调用,来自 super.init(rootViewController: viewController)
初始化!
在不覆盖它的情况下,我想应该调用 UIViewController 的 init(nibName:bundle:)
,但实际上没有。
我仍然不明白为什么重写该方法并调用 super
可以使程序运行得更好。 IMO,在仅调用 super.thisMethod
时覆盖方法是完全无用的,它只是在调用堆栈中添加了一个方法调用。
我一定是遗漏了一些关于 Swift init 方法的基本知识,但我想不通是什么。
最佳答案
这是因为 Swift 继承初始化器的方式。如果您不在当前类中声明任何初始化器,编译器将从父类继承所有初始化器。但是如果你覆盖/添加新的初始化器(并且你用 init(anyVar:)
来做)Swift 不会自动从父类继承初始化器,所以它们不能从子类访问,这会导致运行时崩溃.
如果您对这种行为以外的原因感兴趣,可以查看 Intermediate Swift部分和 WWDC 2014(大约 34 分钟,他们在谈论初始化程序继承)
关于swift - Swift UINavigationController 子类中的强制初始化覆盖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38028940/