Как правильно сделать NSWindowController Singleton в Swift?

У меня есть пример проекта:

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

Мой проект представляет собой раскадровку, приложение на основе документов. Я хотел бы использовать пользовательский переход для переключения видимого состояния окна инспектора. То, что у меня есть, должно работать, но я не могу точно определить, как сделать окно инспектора одноэлементным.

Я считаю, что я должен начать с:

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

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

    override func windowDidLoad()
    {
        super.windowDidLoad()

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

Но как именно должна выглядеть инициализация в моей ситуации, от меня ускользает, тем более что окно находится внутри раскадровки.


person ericg    schedule 04.12.2016    source источник


Ответы (2)


Вы можете выбрать оконный контроллер из сцены оконного контроллера и в инспекторе атрибутов выбрать Single во всплывающем окне под Presentation. Это гарантирует, что переход шоу использует только один экземпляр оконного контроллера. См. этот ответ для получения дополнительной информации.

person Andrew    schedule 22.11.2017

Вот как я бы изменил ваш код:

  1. В Main.storyboard дайте вашему InspectorWindowController идентификатор, например, "Inspector Window Controller"
  2. В InspectorWindowController реализуйте свой синглтон следующим образом:

    static let shared: InspectorWindowController = {
        let storyboard = NSStoryboard(name:"Main", bundle: nil)
        let controller = storyboard.instantiateController(withIdentifier: "Inspector Window Controller")
        return controller as! InspectorWindowController
    }()
    
  3. В Main.storyboard удалите переход от WindowController до InspectorWindowController

  4. В WindowController замените showMyPanel() и hideMyPanel() действия IBA на:

    @IBAction func toggleInspectorPanel( _ sender: AnyObject ) {
        let inspectorWindow = InspectorWindowController.shared.window!
        if inspectorWindow.isVisible {
            inspectorWindow.orderOut(self)
        } else {
            inspectorWindow.makeKeyAndOrderFront(self)
        }
    }
    
  5. Также в WindowController удалите вызов NSLog() из windowDidLoad(). Это вызывает рекурсивный вызов кода инициализации InspectorWindowController.shared.

  6. В Main.storyboard свяжите кнопку панели инструментов инспектора с toggleInspectorPanel()

Синглтон InspectorWindowController.shared будет инициализирован, а панель инспектора загружена (но не показана) при первом обращении к нему.

person Jim Matthews    schedule 06.12.2016
comment
Это, безусловно, (старый) способ решить эту проблему, но я хотел использовать переход. С правильным синглтоном InspectorWindowController это должно быть возможно. Проблема в том, что мне неясно, как именно переопределить различные функции инициализации для достижения одноэлементного шаблона. Если невозможно создать правильный синглтон, это было бы полезно знать. - person ericg; 07.12.2016