Механизм сохранения / восстановления пользовательского интерфейса в Какао через Swift - PullRequest
0 голосов
/ 14 мая 2018

Я хотел бы сохранить состояние Check Box, выйти из приложения, затем снова запустить приложение macOS, чтобы увидеть восстановленное состояние моего Check Box.Но в интерфейсе моего приложения нет восстановленного состояния.

Что я делаю не так?

import Cocoa

class ViewController: NSViewController {

    @IBOutlet weak var tick: NSButton!

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func encodeRestorableState(with coder: NSCoder) {
        super.encodeRestorableState(with: coder)
        coder.encode(tick.state, forKey: "")
    }

    override func restoreState(with coder: NSCoder) {
        super.restoreState(with: coder)       
        if let state = coder.decodeObject(forKey: "") as? NSControl.StateValue {
            tick.state = state
        }
    }
}

Ответы [ 2 ]

0 голосов
/ 13 апреля 2019

На самом деле вам не нужно проходить restorableStateKeyPaths / KVO / KVC, если вы не хотите.

Я застрял в том же состоянии, что и вы, с encodeRestorableState() & restoreState() методы не были вызваны, но выяснили, чего не было.

  1. В Системных настройках> Общие убедитесь, что флажок «Закрыть окна при выходе из приложения» не установлен.
  2. Убедитесь, чтоNSWindow, содержащая ваше представление, имеет включенное поведение "Восстанавливаемый" в IB.NSWindow restorable
  3. Убедитесь, что у вашего NSViewController установлен «Идентификатор восстановления».View controller restoration ID
  4. Ваш NSViewController не будет закодирован, если вы не позвоните invalidateRestorableState().Вы должны вызывать его каждый раз, когда в вашем NSViewController есть состояние, которое изменяется и которое вы хотите сохранить.
  5. Если в NSViewController после его восстановления состояние не изменится, его состояние не будетзакодирован снова при закрытии приложения.Что может привести к тому, что пользовательские состояния не будут восстановлены при перезапуске приложения.Самый простой способ, который я нашел, - это также вызвать invalidateRestorableState() в viewDidLoad(), чтобы это состояние всегда сохранялось.

После всего этого мне даже не пришлось дополнительно реализовывать NSApplicationDelegateили NSWindowRestoration методы протокола.Таким образом, состояние восстановления NSViewController довольно автономно.Восстанавливается только внешнее свойство NSWindow.

0 голосов
/ 15 мая 2018

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

В этом примере у меня есть окно с флажком, и состояние этого флажка представляет собой некоторое пользовательское состояние представления, которое я хочу восстановить при перезапуске приложения.

Проект содержит одно окно с одной кнопкой-флажком. Значение кнопки привязано к свойству myState контроллера представления содержимого окна. Так что с технической точки зрения тот факт, что это флажок управления не имеет значения; на самом деле мы собираемся сохранить и восстановить свойство myState (пользовательский интерфейс позаботится о себе).

Для этого свойство restorable окна имеет значение true (в инспекторе объектов окна), и окну присваивается идентификатор ("PersistentWindow"). NSWindow является подклассом (PersistentWindow), и подкласс реализует свойство restorableStateKeyPaths. Это свойство содержит список пользовательских свойств, которые должны быть сохранены / восстановлены.

Примечание: если вы можете определить восстановление состояния пользовательского интерфейса в виде списка путей свойств, соответствующих ключу-значению, это (безусловно) самое простое решение. Если нет, вы должны реализовать encodeRestorableState / restoreState и отвечать за вызов invalidateRestorableState.

Вот класс пользовательских окон:

class PersistentWindow: NSWindow {

    // Custom subclass of window the perserves/restores UI state

    // The simple way to preserve and restore state information is to just declare the key-value paths
    //  of the properties you want preserved/restored; Cocoa does the rest
    override class var restorableStateKeyPaths: [String] {
       return [ "self.contentViewController.myState" ]
       }

    // Alternatively, if you have complex UI state, you can implement these methods
//  override func encodeRestorableState(with coder: NSCoder) {
//      // optional method to encode special/complex view state here
//  }
//  
//  override func restoreState(with coder: NSCoder) {
//      // companion method to decode special/complex view state
//  }

}

А вот (соответствующая часть) контроллера просмотра контента

class ViewController: NSViewController {

    @objc var myState : Bool = false

    blah, blah, blah
}

(Я создал его как проект приложения Какао, который я мог бы загрузить, если бы кто-то сказал мне, куда я мог бы загрузить его.)

...