Reputation: 2647
I have several popup buttons whose selected tag is saved in the user defaults (by binding the selected tag in the Bindings inspector). Now instead of saving an integer I would like to save a string value (for the simple reason that it makes the user defaults more "readable" and failsafe), but unfortunately didn't find a way to bind a popup button's selected identifier. Is there a solution to this problem?
Upvotes: 2
Views: 590
Reputation: 21373
The bindings for NSPopupButton
can be a little confusing. The various Content* bindings are used to provide the button with its list of possible selections. Content
itself is used to provide a list of objects represented by the items in the pop up button. Content Values
is used to provide the actual values displayed in the pop up button. For example, Content
might be bound to an array of model objects, while Content Values
is bound to a specific key path on those objects, for example name
, because you want to display the value of the name property of each item in the popup button itself.
Similarly, the bindings for selection correspond to this system. Selected Object
means that when a given item is selected, the underlying full object from the Content
array will be selected/set on the bound property, not just the simple displayed string (or number, etc.) value. On the other hand, Selected Value
will indeed bind just the displayed value.
Taken together, and in your case, where you're not using the content bindings, this means that you have two options:
Selected Value
to user defaults.identifier
property and a name
(or whatever you want to call it) property. Bind the Content
binding to an array of those objects, and the Content Values
binding to thatArray.name
.This option is much simpler. Just set up the selected values binding and you're done. It has the major disadvantage that the actual displayed string is the thing being stored in user defaults. This means that if you change the wording of an item, that previously stored selection won't be restored, even if it corresponds directly to the newly-worded item. More importantly, it's not a good idea to make localized -- or potentially localized -- strings semantically important.
This takes a little more work (and code), but it would solve your problem in a robust, "correct" way. For example:
@objcMembers class Option: NSObject {
dynamic var name: String
dynamic var identifier: String
init(name: String, identifier: String) {
self.name = name
self.identifier = identifier
}
}
class ViewController: UIViewController {
@objc dynamic var optionsForPopup = [Option(name: "Item A", identifier: "id 1"),
Option(name: "Item B", identifier: "id 2"),
Option(name: "Item C", identifier: "id 3")]
}
Bind:
Content
to ViewController - optionsForPopup
. Content Values
to ViewController - optionsForPopup.name
. Selected Value
to Shared User Defaults Controller - Controller Key: values
, Model Key Path: WhateverUserDefaultsKeyYouWant
.I've created an example project that implements option 2 here: https://github.com/armadsen/PopupDemo
Upvotes: 3