带screen参数的NSWindow子类初始化触发致命错误问题排查
NSWindow子类初始化崩溃原因及解决办法
崩溃原因
你遇到的致命错误本质是Swift初始化规则的约束导致:
NSWindow.init(contentRect:styleMask:backing:defer:screen:)是便利初始化器,而非NSWindow的核心指定初始化器。它内部会调用父类的指定初始化器init(contentRect:styleMask:backing:defer:)完成基础初始化。- 你的子类
myClass自定义了一个不带convenience修饰的指定初始化器init(),根据Swift规则,子类一旦自定义指定初始化器,就必须显式实现或覆盖父类所有的指定初始化器。由于你未实现init(contentRect:styleMask:backing:defer:),当父类的便利初始化器尝试调用这个未实现的方法时,就会触发崩溃。
解决办法
有两种可行的修复方式:
方式1:显式实现父类的指定初始化器
在子类中添加父类指定初始化器的实现,直接调用父类对应方法即可:
class myClass: NSWindow { init() { // 你的自定义前置逻辑 super.init(contentRect: NSRect(x: 0, y: 0, width: 100, height: 100), styleMask: .borderless, backing: .buffered, defer: false, screen: NSScreen.screens[0]) // 你的自定义后置逻辑 } // 必须覆盖父类的指定初始化器 override init(contentRect: NSRect, styleMask: NSWindow.StyleMask, backing: NSWindow.BackingStoreType, defer flag: Bool) { super.init(contentRect: contentRect, styleMask: styleMask, backing: backing, defer: flag) } // 必须实现NSCoding协议要求的初始化器 required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
方式2:将自定义初始化器改为便利初始化器
给你的init()添加convenience修饰,将其改为便利初始化器,这样它可以直接调用父类的便利初始化器,无需手动覆盖所有指定初始化器:
class myClass: NSWindow { convenience init() { let targetScreen = NSScreen.screens[0] // 先调用父类的初始化器 self.init(contentRect: NSRect(x: 0, y: 0, width: 100, height: 100), styleMask: .borderless, backing: .buffered, defer: false, screen: targetScreen) // 你的自定义逻辑 } // 仍需实现NSCoding要求的初始化器 required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
内容的提问来源于stack exchange,提问作者tim
相关产品推荐
相关产品推荐

