NSViewController 用户界面状态恢复

Posted

技术标签:

【中文标题】NSViewController 用户界面状态恢复【英文标题】:NSViewController User Interface State Restoration 【发布时间】:2016-12-12 15:38:31 【问题描述】:

总结:

使用 Cocoa 的内置用户界面保存机制在我的NSViewController 中保存/恢复NSSearchField 的状态的正确方法是什么?

详情:

我正在开发我的第一个 macOS 应用程序,但我在用户界面的状态恢复方面遇到了一些问题。到目前为止,我的工作已经达到了在我的 NSViewController 子类中调用 encodeRestorableState(with:)restoreState(with:) 方法的程度。

我的视图控制器中有一个NSSearchField,我想保存/恢复搜索字段的状态,包括其文本、任何选择、光标位置以及当前是否处于焦点。

如果我使用以下代码,文本会正确保存和恢复:

override func encodeRestorableState(with coder: NSCoder) 
    super.encodeRestorableState(with: coder)

    coder.encode(searchField.stringValue, forKey: "searchText")


override func restoreState(with coder: NSCoder) 
    super.restoreState(with: coder)

    if let searchText = coder.decodeObject(forKey: "searchText") as? String 
        searchField.stringValue = searchText
    

显然我可以添加更多代码来保存/恢复搜索字段的选择和光标位置等。

我真正的问题是,是否有更好、更合适、更自动的方法来保存和恢复搜索字段的状态?还是需要我为要保存的搜索字段的每个属性编写自己的代码?

我尝试使用:

searchField.encodeRestorableState(with: coder)

和:

searchField.restoreState(with: coder)

在上述两种方法中,但是当我的应用重新启动时,搜索字段中没有出现任何内容。

我也实现了:

override class func restorableStateKeyPaths() -> [String] 
    var keys = super.restorableStateKeyPaths()
    keys.append("searchField.stringValue")

    return keys

其中"searchField" 是我的视图控制器中NSTextField 插座属性的名称。当我的应用程序启动但文本未在搜索字段中恢复时调用此方法。

这个视图控制器是从故事板创建的。视图控制器的identifier 已设置。搜索字段的identifier 也已设置。这个视图控制器是另一个视图控制器的子视图控制器。

我已通读“核心应用程序设计”文档的 User Interface Preservation 部分,但不清楚如何保存/恢复视图控制器的视图,以及其中有多少是自动的还是手动的。

支持 OSX 10.12 和 10.11。任何答案中的 Objective-C 或 Swift 都可以。

【问题讨论】:

“或者,您的自定义响应者对象可以覆盖 restorableStateKeyPaths 方法并使用它来指定要保留的任何属性的关键路径。Cocoa 使用关键路径来定位和保存数据对应的属性。属性必须符合键值编码和键值观察。"? @LeoNatan 我刚试过。我在视图控制器中实现了该方法并返回了NSTextField 属性的名称。该方法被调用,但文本字段未恢复。 我认为它应该包含密钥路径的.stringValue 部分。它应该深入到值本身,而不是控件。 @LeoNatan 不,那也没用。我更新了该代码以返回"searchField.stringValue" 如果您在恢复之前自己设置stringValue,则恢复过程似乎不会被存储值覆盖。 “使用+restorableStateKeyPaths 时不需要上述步骤,因为 KVO 会为我们处理。” bignerdranch.com/blog/cocoa-ui-preservation-yall 【参考方案1】:

为了实现上述效果,让我们创建NSSearchField 和一个名为RestoredWindow 的自定义类,其中只包含一个属性:

import Cocoa

class RestoredWindow: NSWindow 

    override class var restorableStateKeyPaths: [String] 
        return ["self.contentViewController.searchField.stringValue"]
    

将此自定义类分配给 Identity Inspector 中的 Window Controller。

接下来,让我们在 Bindings Inspector 的 Value 部分将 searchField.stringValue 属性绑定到 ViewController

import Cocoa

class ViewController: NSViewController 

    @IBOutlet weak var searchField: NSSearchField!

    override func viewDidLoad() 
        super.viewDidLoad()
    

在此之后,请确保您没有选中 System Preferences -> General 标签中的 Close windows when quitting an app 选项。

现在,在NSSearchField 中输入的文本在退出并再次启动应用程序后恢复。

附言

我尝试过和你一样的方法,但也失败了。这种方法对我不起作用:

override func encodeRestorableState(with coder: NSCoder) 
    coder.encode(searchField.stringValue, forKey: "restore")
    super.encodeRestorableState(with: coder)


override func restoreState(with coder: NSCoder)    
    if let state = coder.decodeObject(forKey: "restore") as? NSSearchField 
        searchField.stringValue = state
    
    super.restoreState(with: coder)

【讨论】:

以上是关于NSViewController 用户界面状态恢复的主要内容,如果未能解决你的问题,请参考以下文章

NSViewController 和界面生成器

NSViewController 没有被创建

从 NSTableView 获取数据到 NSViewController

如何在 Mac OS X 应用程序中从一个 NSViewcontroller 推送到另一个 NSViewcontroller?

如何从 NSViewController 显示视图?

Android——保存和恢复用户状态