class MainViewController: NSViewController { convenience override init() { self.init(nibName: "MainView",bundle: nil) } }
当我切换到6.1 GM2后,它不会编译.看起来这个问题与Swift 1.1中引入的“failable initializers”有关.我已经尝试过方便的重载init?(),方便init?()和override init?(),都没有工作.
那么从今天开始,这是什么正确的方式来覆盖这种初始化器呢?
或者换句话说,使用可用的初始化器的结果是可选的,并且不能使用可选的替代非可选值.并且在类初始化和继承的情况下,您不能将非可选的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!初始化器可以在可用和非可用初始化器之间桥接.您不能将不可用的初始化程序委派给可用的初始化程序,但是您可以从不可用的初始化程序委派给init!初始化和从一个init!初始化器到可用的初始化器.
在这里,要使用的NSViewController初始化程序是完全可用的,所以你用一个init来覆盖它!初始化.然后,您可以声明一个不可用的方便的init代理新的init!初始化.
我们经常倾向于避免IUO,并通过扩展init!因为我们通常希望明确地允许(并且需要处理)失败或明确地禁止它.然而,IUO及其亲属最强大的一般用例之一就是将仅在您的源代码之外保证的条件转化为您的代码可以视为绝对的断言. IBOutlets是一个很好的例子 – 在你的nib / storyboard中,你保证你的IBOutlet变量的状态,但是编译器不知道这一点,就像捆绑资源一样.
这个小代理舞蹈将失败的负担放在你代码中的一个特定的,容易调试的地方 – 如果从init()到super.init(nibName:bundle :)的调用失败,你的应用程序将崩溃.但是,您可以期望该呼叫仅在非常具体(且主要是在开发时)条件下失败.