3

I have a sample project as:

https://github.com/ericgorr/nspanel_show.git

My project is a storyboard, document based application. I would like to use a custom segue to toggle the visible state of the inspector window. What I have should work, but I cannot quite determine how to make the inspector window a singleton.

I believe I should start with:

class InspectorWindowController: NSWindowController
{
    static let sharedInstance = InspectorWindowController()

//    override func init()
//    {
//        
//    }

    override func windowDidLoad()
    {
        super.windowDidLoad()

        NSLog( ":::: %@", InspectorWindowController.sharedInstance );
    }
}

But exactly what the initialization should look like in my situation is escaping me, especially since the window is inside of a storyboard.

ericg
  • 8,413
  • 9
  • 43
  • 77

2 Answers2

4

You can select the window controller from the window controller scene and in the attributes inspector select Single from the pop up under Presentation. This will ensure the show segue only uses a single instance of the window controller. See this answer for more information.

Andrew
  • 7,630
  • 3
  • 42
  • 51
3

Here's how I would modify your code:

  1. In Main.storyboard give your InspectorWindowController an identifier, such as "Inspector Window Controller"
  2. In InspectorWindowController, implement your singleton as follows:

    static let shared: InspectorWindowController = {
        let storyboard = NSStoryboard(name:"Main", bundle: nil)
        let controller = storyboard.instantiateController(withIdentifier: "Inspector Window Controller")
        return controller as! InspectorWindowController
    }()
    
  3. In Main.storyboard delete the segue from WindowController to InspectorWindowController

  4. In WindowController replace the showMyPanel() and hideMyPanel() IBActions with:

    @IBAction func toggleInspectorPanel( _ sender: AnyObject ) {
        let inspectorWindow = InspectorWindowController.shared.window!
        if inspectorWindow.isVisible {
            inspectorWindow.orderOut(self)
        } else {
            inspectorWindow.makeKeyAndOrderFront(self)
        }
    }
    
  5. Also in WindowController, remove the NSLog() call from windowDidLoad(). It causes a recursive call to the InspectorWindowController.shared initialization code.

  6. In Main.storyboard link the Inspector toolbar button to toggleInspectorPanel()

The InspectorWindowController.shared singleton will be initialized, and the inspector panel loaded (but not shown), the first time it is referenced.

Jim Matthews
  • 1,181
  • 8
  • 16
  • 1
    That is certainly a (old) way to solve this problem, but I wanted to use a segue. With a proper InspectorWindowController singleton, this should be possible. The problem is that it is unclear to me how exactly to override the various init functions to achieve the singleton pattern. If it is not possible to create a proper singleton, that would be good to know. – ericg Dec 07 '16 at 00:55