这曾经在Xcode 6.1 beta中起作用:
class MainViewController: NSViewController {
convenience override init() {
self.init(nibName: "MainView", bundle: nil)
}
}
切换到6.1 GM2后,它无法编译。该问题似乎与Swift 1.1中引入的“可失败的初始值设定项”有关。我试过了convenience override init?()
,convenience init?()
并且override init?()
,都没有用。
那么,到目前为止,重写此类初始化程序的正确方法是什么?
您正在init()
通过委派给init?(nibName:bundle:)
,这是一个失败的初始化程序,以实现一个非失败的初始化程序。这是行不通的:如果super.init
调用失败,您将得到一个未初始化的实例,Swift不允许这样做。
换句话说,使用故障初始化程序的结果是可选的,并且不能使用可选的值代替非可选的值。而且在类初始化和继承的情况下,您不能将非可选替换self
为可选的—您只能将self
的状态设置委派给其他初始化程序。
取而代之的是,您可以通过一点点歌舞来删除可选性/失败性:
class MainViewController: NSViewController {
override init!(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
// check state here and provide app-specific diagnostic if it's wrong
}
convenience override init() {
self.init(nibName: "MainView", bundle: nil)
}
// need this, too, or the compiler will complain that it's missing
required init?(coder: NSCoder) {
fatalError("not implemented") // ...or an actual implementation
}
}
一个init!
初始化器产生一个隐式地展开的可选的(IUO) -只是作为一个IUO类型可用于码之间进行桥接,与可选的和非可选值的作品,一个init!
初始值设定failable和非failable初始化之间桥接。你不能从非failable初始化到failable初始化委托,但你可以从非failable初始化一个委托init!
初始化,并从init!
初始到failable初始化。
在这里,NSViewController
您要使用的初始化程序完全失败,因此您可以使用init!
初始化程序覆盖它。然后,您可以声明一个convenience init
委托给新init!
初始化程序的非失败项。
我们通常倾向于通过扩展init!
初始化程序来避免IUO,因为我们通常希望明确允许(并要求处理)失败或明确禁止失败。但是,针对IUO及其同类的最强大的通用用例之一就是将仅在源代码之外保证的条件转换为断言,以使您的代码可以视为无误。IBOutlet
s是一个很好的例子-在nib / storyboard中,您保证IBOutlet
变量的状态,但是编译器不知道这一点-与捆绑包资源所做的任何其他事情一样。
这种委派的小动作将失败的负担放在了代码中特定且易于调试的位置–如果init()
to的调用super.init(nibName:bundle:)
失败,则您的应用程序将崩溃。但是您可以期望该调用仅在非常特定的条件下(并且主要是在开发时)失败。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句