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

 ebt1775010 发布于 2023-01-09 11:56

我正在尝试在Swift中启动一个基于Cocoa项目的新文档,并希望创建一个子类NSWindowController(如Apple的基于文档的应用程序指南中所推荐的).在ObjC中,您将创建一个NSWindowController子类的实例,该子类发送initWithWindowNibName:消息,相应地实现,调用超类方法.

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

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

3 个回答
  • 您需要覆盖NSWindowController(init(),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继承它们,或者通过提供自定义实现作为其定义的一部分 - 那么它会自动继承所有超类便捷初始值设定项.

    2023-01-09 11:58 回答
  • 您可以简单地覆盖windowNibName属性并返回硬编码字符串,而不是覆盖任何init方法.这允许您调用基本的vanilla init方法来创建窗口控制器.

    class WindowController: NSWindowController {
    
        override var windowNibName: String! {
            return "NameOfNib"
        }
    }
    
    let windowController = WindowController()
    

    我更喜欢这个而不是调用,let windowController = WindowController(windowNibName: "NameOfNib")因为nib的名称是一个实现细节,它应该完全封装在窗口控制器类中,并且永远不会暴露在外面(而且它更容易调用WindowController()).

    如果要向init方法添加其他参数,请执行以下操作:

    在您的自定义init方法调用中super.init(window: nil).这将NSWindowControllerwindowNibName属性进入init .

    重写所需的init(coder: NSCoder)方法以配置对象或只是调用fatalError()禁止其使用(运行时为albiet).

    class WindowController: NSWindowController {
    
        var test: Bool
    
        override var windowNibName: String! {
            return "NameOfNib"
        }
    
        init(test: Bool) {
            self.test = test
            super.init(window: nil) // Call this to get NSWindowController to init with the windowNibName property
        }
    
        // Override this as required per the class spec
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented. Use init()")
    
            // OR
    
            self.test = false
            super.init(coder: coder)
        }
    }
    
    let windowController = WindowController(test: true)
    

    2023-01-09 12:00 回答
  • 我只有一个类方法可以解决此问题,该方法调用便捷初始化程序,修改自定义变量,然后返回新对象。

    因此,Objective C init方法如下所示:

    //Class.h
    @class PPPlugInInfo;
    
    @interface PPPlugInInfoController : NSWindowController
    //...
    - (id)initWithPlugInInfo:(PPPlugInInfo *)plugInfo;
    //...
    @end
    
    //Class.m
    #include "Class.h"
    
    @interface PPPlugInInfoController ()
    @property (strong) PPPlugInInfo *info;
    @end
    
    @implementation PPPlugInInfoController
    
    - (id)initWithPlugInInfo:(PPPlugInInfo *)plugInfo;
    {
        if (self = [self initWithWindowNibName:@"PPPlugInInfoController"]) {
            self.info = plugInfo;
        }
        return self;
    }
    
    @end
    

    这是我做Swift版本的方法:

    class PPPluginInfoController: NSWindowController {
        private var info: PPPlugInInfo!
        class func windowControllerFromInfo(plugInfo: PPPlugInInfo) -> Self {
            var toRet = self(windowNibName:"PPPlugInInfoController")
            toRet.info = plugInfo
    
            return toRet
        }
    }
    

    2023-01-09 12:00 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有