NSWindowController 指定初始化谜题

Posted

技术标签:

【中文标题】NSWindowController 指定初始化谜题【英文标题】:NSWindowController designated initializer puzzle 【发布时间】:2018-07-11 21:59:35 【问题描述】:

我正在尝试使这段代码工作:

class MyWindowController: NSWindowController

  let thing: Thing

  convenience init(thing: Thing)
  
    self.thing = thing

    super.init(windowNibName: NSNib.Name(rawValue: "MyNib"))
  

当然,问题在于便利初始化程序不能从超类调用init。那么如何初始化我的thing 并且仍然能够调用init(windowNibName:),它本身就是一个便利的初始化程序?我宁愿不必自己重新实现 nib 加载,但如果我只能使用指定的初始化程序,我该如何避免呢?

【问题讨论】:

如果您的子类没有声明自己的指定初始化程序,它将继承其超类的便利初始化程序。您的问题更多是您的初始化程序不能成为便利初始化程序,因为您的 thing 属性需要初始化。 【参考方案1】:

根据NSWindowController 文档:

您还可以实现NSWindowController 子类,以避免在实例化窗口控制器时要求客户端代码获取相应的nib 文件名并将其传递给init(windowNibName:)init(windowNibName:owner:)。最好的方法是重写 windowNibName 以返回 nib 的文件名并通过将 nil 传递给 init(window:) 来实例化窗口控制器。使用 init(window:) 指定的初始化器可以简化对 Swift 初始化器要求的遵守。

您可以将您的类实现为:

class MyWindowController: NSWindowController

    let thing: Thing

    override var windowNibName: NSNib.Name? 
        return NSNib.Name(rawValue: "MyNib")
    

    init(thing: Thing) 
        self.thing = thing

        super.init(window: nil)
    

    required init?(coder: NSCoder) 
        fatalError("init(coder:) has not been implemented")
    

【讨论】:

谢谢,我忘记了windowNibName。这个问题有更通用的解决方案吗?还是总是需要这样的解决方法? “这个问题”到底是什么?您的意思是在使用 super.init... 时需要调用指定的初始化程序吗?这完全取决于所涉及的类。 如果我在另一个班级遇到了类似的情况但没有windowNibName 的等价物怎么办?似乎这是一种无法从子类调用便利初始化程序的解决方法。我不明白这个限制的目的。 每个案例都需要以任何对所涉及的类有意义的方式来处理。请参阅 Swift 书中初始化章节的 Class Inheritance and Initialization 部分。

以上是关于NSWindowController 指定初始化谜题的主要内容,如果未能解决你的问题,请参考以下文章

来自笔尖的 NSWindowController 子类初始化不使用 -initWithCoder:?

15-谜问题

LeetCode——滑动谜题

如何通过按 ESC 键关闭窗口(NSWindowController)?

通过 NSWindowController 从窗口中删除 RepresentedFilename

NSWindowController showWindow: 闪烁窗口