通过Swift在Cocoa中的UI保存/恢复机制

问题描述 投票:0回答:2

我想保存Check Box的状态,退出应用程序,然后再次启动macOS应用程序以查看我的Check Box的恢复状态。但我的应用程序的UI中没有恢复状态。

我究竟做错了什么?

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
        }
    }
}
macos cocoa swift4 restore savestate
2个回答
2
投票

据我所知,这是实现窗口和/或其内容的自定义UI状态恢复所需的绝对最小值。

在这个例子中,我有一个带复选框的窗口,复选框的状态表示我想在重新启动应用程序时恢复的自定义视图状态。

该项目包含一个带有单个复选框按钮的窗口。按钮的值绑定到窗口内容视图控制器的myState属性。因此,从技术上讲,这是一个复选框控件的事实是无关紧要的;我们实际上将保留和恢复myState属性(UI自己处理)。

为了使其工作,窗口的restorable属性设置为true(在窗口对象检查器中),并为窗口分配了一个标识符("PersistentWindow")。 NSWindow是子类(PersistentWindow),子类实现restorableStateKeyPaths属性。此属性列出要保留/还原的自定义属性。

注意:如果您可以根据符合键值的属性路径列表定义UI状态恢复,那么(到目前为止)是最简单的解决方案。如果没有,你必须实现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
}

(我将它构建为一个Cocoa应用程序项目,如果有人告诉我可以将其上传到哪里,我可以上传。)


1
投票

实际上,如果你不想,你不必通过restorableStateKeyPaths / KVO / KVC。

我被卡在与你相同的状态,没有被调用的encodeRestorableState()restoreState()方法,但发现了缺少的东西。

  1. 在“系统偏好设置”>“常规”中,确保未选中“退出应用时关闭窗口”。
  2. 确保包含您视图的NSWindow在IB中启用了“可恢复”行为。 NSWindow restorable
  3. 确保您的NSViewController设置了“恢复ID”。 View controller restoration ID
  4. 除非你打电话给NSViewController,否则你的invalidateRestorableState()不会被编码。每当你的NSViewController中的状态发生变化并且你想要保存时,你需要调用它。
  5. NSViewController恢复后状态没有变化时,关闭应用程序时其状态不会再次编码。这将导致重新启动应用程序时无法恢复自定义状态。我找到的最简单的方法是在invalidateRestorableState()中调用viewDidLoad(),以便始终保存状态。

完成所有这些后,我甚至不必另外实现NSApplicationDelegateNSWindowRestoration协议方法。所以NSViewController的状态恢复是相当独立的。只有外部财产是可恢复的NSWindow

© www.soinside.com 2019 - 2024. All rights reserved.