如何在字典中管理多个NSWindows

时间:2018-03-21 10:15:29

标签: swift macos

我想做的事情:

我目前正在开发一个命令行工具,为每个可用的桌面空间创建一个模糊的窗口。我将这些窗口保存在字典中,其中spaceIdentifierkeyNSWindowvalue。 为了使窗口与空间保持同步,我会定期检查是否有新的空格或是否有空格。

我的代码:

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中的内存管理并不那么自信。 我真的很感激,如果有人能告诉我安全关闭某种字典/地图/其他组织的窗户的最佳方式。

PS:

如果您想知道为什么我不使用.canJoinAllSpaces而不是为每个空间创建窗口:使用.canJoinAllSpaces时,如果空格可以看到模糊的NSEffectView在空格上闪烁有不同的桌面图像。避免这种情况的唯一方法是为每个空间创建单独的窗口。

0 个答案:

没有答案