Summary:
What's the proper way to save/restore the state of an NSSearchField
in my NSViewController
using the built-in user interface preservation mechanism of Cocoa?
Details:
I'm working on my first macOS app and I'm having a little trouble with state restoration for my user interface. So far I have it working to the point where the encodeRestorableState(with:)
and restoreState(with:)
methods are called in my NSViewController
subclass.
I have an NSSearchField
in my view controller and I want to save/restore the state of the search field including its text, any selection, the cursor position, and whether it is currently in focus or not.
If I use the following code, the text is properly saved and restored:
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 } }
Obviously I can add more code to save/restore the search field's selection and cursor position, etc.
My real question is, is there a better, proper, more automatic way to save and restore the search field's state? Or is it required that I write my own code for each attribute of the search field I wish to save?
I tried using:
searchField.encodeRestorableState(with: coder)
and:
searchField.restoreState(with: coder)
in the two above methods but that didn't result in anything appearing in the search field when my app was restarted.
I also implemented:
override class func restorableStateKeyPaths() -> [String] { var keys = super.restorableStateKeyPaths() keys.append("searchField.stringValue") return keys }
where "searchField"
is the name of the NSTextField
outlet property in my view controller. This method is called when my app is launched but the text was not restored in the search field.
This view controller is created from a storyboard. The view controller's identifier
is set. The search field's identifier
is set as well. This view controller is a child view controller of another view controller.
I've read through the User Interface Preservation section of the "The Core App Design" document but it's unclear on how a view controller's views are saved/restored and how much of this is automatic versus manual.
Supporting OSX 10.12 and 10.11. Objective-C or Swift in any answers is fine.
To achieve aforementioned effect let's create NSSearchField
and a custom class named RestoredWindow
containing just one property:
import Cocoa class RestoredWindow: NSWindow { override class var restorableStateKeyPaths: [String] { return ["self.contentViewController.searchField.stringValue"] } }
Assign this custom class to Window Controller in Identity Inspector.
Next, let's bind searchField.stringValue
property to ViewController
in Value
section of Bindings Inspector.
import Cocoa class ViewController: NSViewController { @IBOutlet weak var searchField: NSSearchField! override func viewDidLoad() { super.viewDidLoad() } }
After this, make sure you haven't checked
Close windows when quitting an app
option in yourSystem Preferences
->General
tab.
Now, entered text in NSSearchField
restored after quitting and launching the app again.
P.S.
I've tried the same way as you but failed too. This approach doesn't work for me:
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) }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With