小编典典

在Swift和init中子类化NSWindowController(windowNibName)

swift

我正在尝试在Swift中启动一个新的基于文档的Cocoa项目,并想创建一个子类NSWindowController(如在基于文档的应用程序的Apple指南中所建议的那样)。在ObjC中,您将创建一个NSWindowController子类的实例来发送initWithWindowNibName:消息,并通过调用superclasses方法相应地实现了该消息。

在斯威夫特init(windowNibName)仅作为一种方便的初始化,指定初始化的NSWindowController就是init(window)这显然想让我在一个窗口中通过。

我不能super.init(windowNibName)从我的子类中调用,因为它不是指定的初始化器,所以显然我必须实现convenience init(windowNibName),而后者又需要调用self.init(window)。但是,如果我只有nib文件,该如何访问nib文件的窗口以发送给该初始化程序?


阅读 449

收藏
2020-07-07

共1个答案

小编典典

您需要覆盖NSWindowControllerinit()init(window)init(coder))的所有三个指定的初始化器,或者都不重写它们,在这种情况下,您的子类将自动继承,init(windowNibName)而所有其他便捷的初始化器都将覆盖,您将能够使用超类的便捷的初始化器来构造它:

// this overrides none of designated initializers
class MyWindowController: NSWindowController {
    override func windowDidLoad() {
        super.windowDidLoad()
    }
}

// this one overrides all of them
//
// Awkwardly enough, I see only two initializers 
// when viewing `NSWindowController` source from Xcode, 
// but I have to also override `init()` to make these rules apply.
// Seems like a bug.
class MyWindowController: NSWindowController
{
    init()
    {
        super.init()
    }

    init(window: NSWindow!)
    {
        super.init(window: window)
    }

    init(coder: NSCoder!)
    {
        super.init(coder: coder)
    }

    override func windowDidLoad() {
        super.windowDidLoad()
    }
}

// this will work with either of the above
let mwc: MyWindowController! = MyWindowController(windowNibName: "MyWindow")

语言指南中的“初始化/自动初始化继承”对此进行了介绍:

但是,如果满足某些条件,则会自动继承超类初始化器。实际上,这意味着您不需要在许多常见情况下编写初始化程序覆盖,并且可以在安全的情况下以最小的努力继承超类初始化程序。

假设为子类中引入的任何新属性提供默认值,则适用以下两个规则:

规则1 如果子类没有定义任何指定的初始化器,它将自动继承其所有超类指定的初始化器。

规则2
如果您的子类提供了其所有超类指定的初始值设定项的实现(通过按规则1继承它们,或通过提供自定义实现作为其定义的一部分),则它会自动继承所有超类的便利初始值设定项。

2020-07-07