我目前正在开发一个命令行工具,为每个可用的桌面空间创建一个模糊的窗口。我将这些窗口保存在字典中,其中spaceIdentifier
是key
而NSWindow
是value
。
为了使窗口与空间保持同步,我会定期检查是否有新的空格或是否有空格。
import AppKit
import Foundation
func createBlurWindow(screen: NSScreen?, contentRect: NSRect, brightness: Int) -> NSWindow
{
# irrelevant code that creates a blurred window
}
class AppController: NSObject, NSApplicationDelegate
{
var spaceWindowList: [NSNumber: NSWindow] = [:]
func applicationDidFinishLaunching(_ aNotification: Notification)
{
self.manageWindows()
Timer.scheduledTimer(timeInterval: 5.0, target: self, selector: #selector(self.manageWindows), userInfo: nil, repeats: true)
}
@objc func manageWindows()
{
// create windows
for scr in NSScreen.screens {
let scrHeight = scr.frame.height
let scrWidth = scr.frame.width
let windowHeight = CGFloat(22)
let size = CGRect(x: 0, y: scrHeight-windowHeight, width: scrWidth, height: windowHeight)
let currentScreenSpaces = WindowHelper.getSpacesforScreen(scr)
for space in currentScreenSpaces!
{
if self.spaceWindowList[space] == nil
{
let w = createBlurWindow(screen: scr, contentRect: size, brightness: 9)
let windowID = NSNumber.init(value: w.windowNumber)
// @TODO this may fail if the space was created just now -> fix this by waiting some time
WindowHelper.moveWindow(windowID, toSpace: space)
self.spaceWindowList[space] = w
// debuginfo
let displayNr = scr.deviceDescription[NSDeviceDescriptionKey("NSScreenNumber")]!
print(getTime(), " Display:", displayNr, " added Window(", windowID , ") for Space: ", space, separator: "")
}
}
}
let currentSpaces = WindowHelper.getAllSpaces()
for (space, window) in self.spaceWindowList
{
// destroy window if space was closed
if !(currentSpaces?.contains(space))!
{
window.close()
//self.spaceWindowList.removeValue(forKey: space)
// debuginfo
print(getTime(), "Destroyed window of closed Space:", space)
}
}
}
}
let app = NSApplication.shared
let controller = AppController()
app.delegate = controller
app.run()
可以找到完整的来源here
当检测到空格已关闭时,我尝试以编程方式关闭相应的NSWindow,但是下次manageWindows()
被称为应用程序段错误:for (space, window) in self.spaceWindowList
。调试我激活的zombieobjects并获得以下errormessage -[NSWindow retain]: message sent to deallocated instance 0x101241150
我不明白为什么下次spaceWindowList
迭代时仍有指向我窗口的指针。我还尝试用nil
self.spaceWindowList.removeValue(forKey: space)
字典条目,但这也会导致段错误。
我对swift和macdev来说相当新,所以我对swift中的内存管理并不那么自信。 我真的很感激,如果有人能告诉我安全关闭某种字典/地图/其他组织的窗户的最佳方式。
如果您想知道为什么我不使用.canJoinAllSpaces
而不是为每个空间创建窗口:使用.canJoinAllSpaces
时,如果空格可以看到模糊的NSEffectView在空格上闪烁有不同的桌面图像。避免这种情况的唯一方法是为每个空间创建单独的窗口。