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

如何实现NSWindow程序化创建与销毁的正确生命周期?

程序化创建NSWindow的正确生命周期实现

问题根源分析

你的代码存在两个核心问题:

  1. 直接持有NSWindow实例而非NSWindowController,违背了Apple设计的窗口生命周期管理逻辑——NSWindowController才是负责窗口创建、显示、销毁全生命周期的容器类。
  2. 局部创建的NSWindowController会被ARC立即释放,导致窗口失去正确的管理容器;而直接移除windowController后,窗口被提前释放但系统仍有后续消息发送,引发野指针崩溃。

修正后的代码实现

class Wins: NSObject, NSWindowDelegate {
    // 改为持有NSWindowController,而非直接持有NSWindow
    private var windowControllers = Set<NSWindowController>()

    func createWindow() {
        let newWindow = NSWindow(
            contentRect: .init(origin: .zero, size: .init(width: 300, height: 300)),
            styleMask: [.titled, .closable, .miniaturizable, .resizable], // 用枚举替代rawValue,可读性更强
            backing: .buffered,
            defer: false
        )
        newWindow.title = "New Window"
        newWindow.isOpaque = false
        newWindow.isMovableByWindowBackground = true
        newWindow.backgroundColor = NSColor(calibratedHue: 0, saturation: 1.0, brightness: 0, alpha: 0.7)
        newWindow.delegate = self // 设置代理监听窗口关闭事件

        let windowController = NSWindowController(window: newWindow)
        windowController.window?.makeKeyAndOrderFront(nil)
        windowControllers.insert(windowController) // 强引用控制器,维持其生命周期
    }

    // 监听窗口即将关闭事件,自动清理控制器引用
    func windowWillClose(_ notification: Notification) {
        guard let window = notification.object as? NSWindow,
              let controller = window.windowController else { return }
        windowControllers.remove(controller)
    }

    func closeAll() {
        // 遍历集合副本,避免遍历过程中修改原集合引发异常
        for controller in windowControllers {
            controller.close()
        }
    }
}

关键修正点说明

  • 用NSWindowController管理窗口:NSWindowController会自动处理窗口的内存管理逻辑,避免手动持有窗口导致的引用循环或释放不及时问题。当控制器被释放时,其持有的窗口也会被正确回收。
  • 实现windowWillClose代理:窗口关闭时触发该方法,从集合中移除对应的控制器,解除强引用,让ARC可以正常回收控制器和窗口的内存。
  • 避免直接遍历修改集合:关闭所有窗口时遍历集合的副本,防止遍历过程中集合元素被移除导致的遍历异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 15:35:51