纯Swift无Storyboard创建NSWindow后,无法获取隐藏窗口的问题咨询
隐藏状态下获取NSWindow的解决方案
问题根源
NSApp.windows仅返回当前处于可见状态的应用窗口,当调用orderOut(nil)或setIsVisible(false)隐藏窗口后,窗口会从该数组中移除,因此原查找方法失效。
可行解决方法
1. 自行维护全局窗口字典
创建全局字典存储所有窗口实例,以窗口identifier为键,无论窗口是否隐藏都能直接获取:
// 全局存储窗口的字典,建议放在AppDelegate或专门的工具类中 private var appWindows: [NSUserInterfaceItemIdentifier: NSWindow] = [:] // 创建窗口时加入字典 let window = NSWindow(contentRect: pInstruction.GetFrame(), styleMask: [.miniaturizable, .closable, .resizable, .titled], backing: .buffered, defer: false) let windowID = NSUserInterfaceItemIdentifier("WinID1") window.identifier = windowID appWindows[windowID] = window // 存入字典 window.title = "Some Title" window.contentViewController = MyViewController() window.makeKeyAndOrderFront(nil) // 获取窗口的工具方法 static func getWindow(_ windowID: NSUserInterfaceItemIdentifier) -> NSWindow? { return appWindows[windowID] } // 窗口销毁时需移除条目,避免内存泄漏 // 例如在窗口关闭的回调中执行: // appWindows.removeValue(forKey: windowID)
2. 使用NSWindowController管理窗口
通过NSWindowController持有窗口实例,控制器会持续保留对窗口的引用,即使窗口被隐藏:
// 创建窗口并封装到NSWindowController let window = NSWindow(contentRect: pInstruction.GetFrame(), styleMask: [.miniaturizable, .closable, .resizable, .titled], backing: .buffered, defer: false) let windowID = NSUserInterfaceItemIdentifier("WinID1") window.identifier = windowID window.title = "Some Title" window.contentViewController = MyViewController() let windowController = NSWindowController(window: window) // 存储控制器到全局容器 private var windowControllers: [NSUserInterfaceItemIdentifier: NSWindowController] = [:] windowControllers[windowID] = windowController // 显示窗口 windowController.showWindow(nil) // 获取隐藏窗口的方法 static func getWindow(_ windowID: NSUserInterfaceItemIdentifier) -> NSWindow? { return windowControllers[windowID]?.window }
3. 利用NSApplication的allWindows属性(macOS 10.12+)
macOS 10.12及以上版本中,NSApp.allWindows会返回应用的所有窗口(包括隐藏状态),直接替换原方法中的NSApp.windows即可:
static func getWindow(_ pWindowID: NSUserInterfaceItemIdentifier) -> NSWindow? { for window in NSApp.allWindows { if window.identifier == pWindowID { return window } } return nil }
注意事项
- 使用全局字典存储窗口时,务必在窗口销毁(如用户关闭窗口)时移除对应条目,防止内存泄漏。
- 使用
allWindows时,需确保窗口identifier唯一,避免匹配到系统自动创建的辅助窗口或面板。
内容的提问来源于stack exchange,提问作者Sidharth Mahesh Nair
相关产品推荐
相关产品推荐

