UIViewControllerclass 定义了一个指定的初始化器,init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)没有方便的初始化器,但是,可以编写以下代码行并编译它(Xcode 6.1.1)
let vc = UIViewController()
这怎么可能?
根据Swift书,这里是初始化继承的规则
规则 1 如果您的子类没有定义任何指定的初始值设定项,它会自动继承其所有超类指定的初始值设定项。
规则 2 如果您的子类提供了其所有超类指定初始化器的实现——或者按照规则 1 继承它们,或者通过提供自定义实现作为其定义的一部分——那么它会自动继承所有超类便利初始化器。”
摘自:Apple Inc. “The Swift Programming Language”。电子书。 https://itun.es/us/jEUH0.l
因此UIViewController无法init()从其祖先超类继承该方法NSObject,那么初始化程序从何而来?
另一方面,因为每个 swift 类最终都必须调用其指定的初始化程序,这是否意味着initWithCoder:最终也会调用init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)? 然而,在实践中似乎并非如此。
Swift 书中的规则适用于 Swift 中定义的类。UIViewController是一个从 ObjC 导入的类,因此它的行为受 ObjC 规则(或缺乏规则)的约束。
在 ObjC 中,指定的初始化器链接模式是你应该做的事情(不像在 Swift 中编译器强制它是你唯一可以做的事情)。如果您调用继承的初始化程序而不是指定的初始化程序,您将返回一个实例……但不能保证所述实例处于合理状态。(事实上,你几乎可以肯定它不会。)ObjC 类的作者有时通过实现你不应该调用的初始化程序并让它们抛出异常来练习防御性编码,但这似乎不是这里的情况。
这个特殊案例可以说是某种错误——向 Apple 提交一个文件并不是一个坏主意。当从导入的 ObjC API 创建对象时,Swift 应该强制执行初始化规则(在这种情况下UIViewController,需要在 ObjC 中声明其指定的初始化规则NS_DESIGNATED_INITIALIZER),或者UIViewController应该实施以防止不正确的初始化。(尽管“修复”其中任何一个都可能存在兼容性副作用。)
| 归档时间: |
|
| 查看次数: |
324 次 |
| 最近记录: |