You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

继承NSWindow创建SettingWindow时出现unrecognized selector错误

为什么继承NSWindow时调用init(contentViewController:)会触发未识别选择器错误?

错误核心原因

你遇到的-[SettingWindow windowWithContentViewController:]: unrecognized selector sent to instance错误,本质是对NSWindow初始化器的误解:

  • NSWindow没有init(contentViewController:)这个实例初始化器——你调用的这个方法,实际上是NSWindow提供的类级便利构造器(对应Objective-C的类方法windowWithContentViewController:),而非实例初始化器。
  • 当你在子类的自定义init()里尝试调用super.init(contentViewController:)时,Swift会将这个调用映射到Objective-C的类方法,但你的子类并没有重写该类方法,导致运行时无法找到对应实现,从而抛出未识别选择器错误。

第二个代码正常运行的原因

第二个代码能正常工作,是因为它遵循了Cocoa类的初始化规则:

  • 调用了NSWindow的指定初始化器init(contentRect:styleMask:backing:defer:)——这是NSWindow类唯一的指定初始化器,所有子类必须通过调用它来完成父类的初始化。
  • 之后手动设置contentViewController,是直接给实例属性赋值,属于合法的实例操作,不会触发任何隐式的类方法调用。

补充说明(Cocoa初始化规则)

对于Cocoa框架中的类,很多看似实例初始化器的方法其实是类便利构造器。子类化这些类时,必须严格调用父类的指定初始化器,而非便利构造器。NSWindow仅拥有init(contentRect:styleMask:backing:defer:)这一个指定初始化器,其他所有初始化方式都是基于它封装的便利构造器。

修正第一个代码的示例

如果想保留类似第一个代码的简洁写法,可以在子类中正确实现初始化逻辑:

import Cocoa

final class SettingWindow: NSWindow {
    static let shared = SettingWindow()

    private let tabViewController: NSTabViewController

    private init() {
        tabViewController = NSTabViewController()
        tabViewController.tabStyle = .toolbar
        tabViewController.title = "Setting"

        // 必须调用父类的指定初始化器
        super.init(contentRect: .zero, styleMask: [.titled, .closable, .resizable], backing: .buffered, defer: false)
        contentViewController = tabViewController
    }

    // Cocoa类子类必须实现required初始化器(应对Storyboard/XIB场景)
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

内容的提问来源于stack exchange,提问作者yys

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 11:46:21