如何获取指定NSWindow对应的当前Space/Desktop?
获取NSWindow所在的当前Space/Desktop索引
当然可以实现你想要的myWindow.spaceIndex属性!不过要注意macOS的Space(桌面)信息属于需要权限的系统资源,下面我会分享两种可行的实现方案,都能让你直接通过窗口实例拿到对应的Space索引:
方案一:使用Accessibility API(性能更优)
这种方案直接调用系统的Accessibility框架API,响应速度更快。我们可以给NSWindow写一个扩展,实现spaceIndex计算属性:
import Cocoa import ApplicationServices extension NSWindow { var spaceIndex: Int? { // 获取当前窗口的ID guard let windowID = self.windowNumber as CFNumber else { return nil } // 获取当前应用的AXUIElement实例 let currentApp = NSRunningApplication.current let appAXElement = AXUIElementCreateApplication(currentApp.processIdentifier) // 获取当前桌面的所有Space var spaces: AnyObject? let getSpacesStatus = AXUIElementCopyAttributeValue(appAXElement, kAXSpacesAttribute as CFString, &spaces) guard getSpacesStatus == .success, let spacesArray = spaces as? [AXUIElement] else { print("Failed to retrieve spaces - check accessibility permissions") return nil } // 遍历每个Space,查找包含当前窗口的那个 for (index, space) in spacesArray.enumerated() { var windowsInSpace: AnyObject? let getWindowsStatus = AXUIElementCopyAttributeValue(space, kAXWindowsAttribute as CFString, &windowsInSpace) if getWindowsStatus == .success, let windowIDs = windowsInSpace as? [CFNumber], windowIDs.contains(windowID) { // 返回索引(这里从1开始,符合系统显示的Space编号) return index + 1 } } return nil } }
注意事项
- 你需要在App的
Info.plist中添加NSAccessibilityUsageDescription键,说明App需要访问辅助功能的原因(比如"需要获取窗口所在的桌面信息以提供更好的用户体验")。 - 用户必须在系统设置 > 隐私与安全性 > 辅助功能中给你的App授权,否则API会返回
nil。
方案二:使用AppleScript桥接(代码更简洁)
如果你觉得Accessibility API的代码有点繁琐,也可以用AppleScript来实现,代码更直观,但执行效率会稍低一些:
import Cocoa extension NSWindow { var spaceIndex: Int? { let scriptSource = """ tell application "System Events" set targetWindowID to \(self.windowNumber) set allSpaces to spaces of current desktop repeat with spaceIndex from 1 to count of allSpaces set spaceWindows to windows of item spaceIndex of allSpaces if targetWindowID is in (id of spaceWindows) then return spaceIndex end if end repeat end tell """ let appleScript = NSAppleScript(source: scriptSource) var error: NSDictionary? guard let scriptResult = appleScript?.executeAndReturnError(&error), let index = scriptResult.int32Value else { print("AppleScript execution failed: \(error ?? [:])") return nil } return Int(index) } }
注意事项
- 同样需要辅助功能权限,并且在
Info.plist中添加权限描述。 - AppleScript的执行可能会有轻微延迟,适合对性能要求不高的场景。
额外说明
- 两种方案返回的索引都是从1开始的(和系统顶部状态栏显示的Space编号一致),如果需要从0开始的索引,只需把
return index + 1改成return index即可。 - 如果窗口不在任何可见Space中(比如最小化或隐藏),
spaceIndex会返回nil。
内容的提问来源于stack exchange,提问作者Giuseppe Salvo
相关产品推荐
相关产品推荐

