如何在Swift中初始化NSWindowController?

Voi*_*ain 9 cocoa appkit swift

我想从一个nib文件初始化一个窗口控制器对象,这很简单吗?但我根本无法让它发挥作用.

根据我之前在ObjC的经验,我写下了以下代码:

init()  {
    super.init(windowNibName: "SplitWindowController")
}
Run Code Online (Sandbox Code Playgroud)

在app委托文件中,我只需初始化并显示窗口:

var myWindowController: MyWindowController = MyWindowController()
myWindowController.showWindow(self)
myWindowController.window.makeKeyAndOrderFront(nil)
Run Code Online (Sandbox Code Playgroud)

但是编译器给了我这个错误:Must call a designated initializer of the superclass 'NSWindowController'.并根据雨燕版本NSWindowController定义,只有3个指定的初始值,即init(),init(window),init(coder).我不知道接下来该做什么.我应该NSCoder从一个nib文件构建一个,我不知道该怎么办?

mil*_*los 6

你快到了.您确实可以init()以与您习惯的Obj-C代码等效的方式覆盖作为便利初始化程序:

import Cocoa

class MyWindowController: NSWindowController {

    override convenience init() {
        self.init(windowNibName: "<xib name>")
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,您所呼叫init(windowNibName:)self,因为init()作为一个方便的初始化器,你仍然继承所有从超类中的initialisers.来自文档:

规则1:指定的初始化程序必须从其直接超类调用指定的初始化程序.

规则2:便捷初始值设定项必须从同一个类调用另一个初始值设定项.

规则3:便捷初始化程序必须最终调用指定的初始化程序.

另外,正如上面提到的@weichsel,请确保将类的File's Owner类设置为NSWindowController(在上面的示例中,将是MyWindowController),然后将其window插座与窗口本身连接.

话虽这么说,我不确定为什么编译器要求override添加关键字.尽管NSWindowController是一个NSResponder定义了一个的子类,init()但是即使它实现了一个等效的继承层次结构,下面的代码也可以毫无问题地编译:

class A {
    init() { }
}

class B: A {
    init(Int) {
        super.init()
    }
    convenience init(String) {
        self.init(5)
    }
}

class C: B {
    convenience init() {
        self.init("5")
    }
}
Run Code Online (Sandbox Code Playgroud)


Tho*_*ing 4

NSWindowController有 2 个指定的初始值设定项:

init(window: NSWindow!)
init(coder: NSCoder!)
Run Code Online (Sandbox Code Playgroud)

创建子类时,应该调用其超类的指定初始值设定项。最新版本的 Xcode 强制执行此操作。通过内置语言机制 (Swift) 或通过NS_DESIGNATED_INITIALIZER宏 (Objective-C)。

Swift 还要求您在重写便利初始化器时调用指定初始化器的超类。
来自《Swift 编程指南》的“初始化:指定初始化器和便利初始化器”部分:

如果您要重写的初始化程序是便利初始化程序,则您的重写必须根据初始化程序链接中上述规则从其自己的子类调用另一个指定的初始化程序。

在你的情况下,你可能应该覆盖init(window: NSWindow!)并从那里调用超级的对应部分。