title: How to manage multiple NSWindows in a dictionary
body: <h2>What I'm trying to do:</h2>
  
  <p>I'm currently developing a Command-Line-Tool that creates a blurred window for each desktop space available. I save these windows in a dictionary where the <code>spaceIdentifier</code> is the <code>key</code>and the <code>NSWindow</code> is the <code>value</code>.
  In order to keep the windows in sync with the spaces I periodically check if there are new spaces or if spaces are closed.</p>
  
  <h2>My Code:</h2>
  
  <pre><code>import AppKit
  import Foundation
  
  func createBlurWindow(screen: NSScreen?, contentRect: NSRect, brightness: Int) -&gt; 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 -&gt; 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()
  </code></pre>
  
  <p>The complete source can be found <a href="https://github.com/kinglouie/BlurWindow" rel="nofollow noreferrer">here</a></p>
  
  <h3>My Problem:</h3>
  
  <p>When detecting that a space was closed I try to programatically close the corresponding NSWindow, however the next time <code>manageWindows()</code> is called the application segfaults on this loop: <code>for (space, window) in self.spaceWindowList</code>. To debug I activated zombieobjects and got the following errormessage <code>-[NSWindow retain]: message sent to deallocated instance 0x101241150</code>
  I don't understand why there is still a pointer to my window the next time <code>spaceWindowList</code> is iterated. I also tried to <code>nil</code> the dictionary entry with <code>self.spaceWindowList.removeValue(forKey: space)</code> but that also lead to a segfault.</p>
  
  <p>I'm fairly new to swift and macdev in general so I'm not that confident with memory management in swift. 
  I would really appreciate if someone could tell me the best way to safely close windows organized in some kind of dictionary/map/whatever.</p>
  
  <h3>PS:</h3>
  
  <p>If you are wondering why I don't use <code>.canJoinAllSpaces</code> instead of creating the window for each space: When using <code>.canJoinAllSpaces</code> you can see the blurred NSEffectView flickering on a space change if the spaces have different desktop images. The only way to circumvent this is to create individual windows for each space.</p>