Reputation: 95355
Say I have the following array of dictionaries:
{
{
isoName => en,
fullName => English,
localName => English
},
{
isoName => de,
fullName => German,
localName => Deutsch
},
{
isoName => fr,
fullName => French,
localName => français
}
}
How can I bind the fullName
values to the values of an NSPopUpButton control but bind the selection's isoName
to NSUserDefaults? I have an NSArrayController set up with an array like the above, and my NSPopUpButton is bound to this controller with the model key path as "fullName", but I want to keep the isoName
in the NSUserDefaults. Is this possible? Is there a better way to approach this?
Upvotes: 1
Views: 1539
Reputation: 96363
First off, create a model object class representing a language, and make these dictionary pairs properties of the model objects. Dictionaries don't work well with Bindings, in my experience; the Bindings system wants real model objects.
Next, create a controller object to hold these model objects. I'll call it LanguageKeeper. It has three properties:
languages
(NSArray of Language objects)selectedLanguage
selectedLanguageISOName
Expose the last one as a binding. Also, make one of the last two properties derivative of the other. I'd make the ISOName property derivative: the getter will return self.selectedLanguage.ISOName
, and setter will perform the look-up for a given ISO name and set self.selectedLanguage
to that language object. Make sure to implement keyPathsForValuesAffectingSelectedLanguage
and keyPathsForValuesAffectingSelectedLanguageISOName
, and have the other property's name in the set that each method returns.
First, bind the NSArrayController's content-array binding to the languages
property of the LanguageKeeper.
Then, bind three properties on the pop-up button:
arrangedObjects
property, leaving the model key path empty (or set it to self
if this causes problems)arrangedObjects
property, with a model key path of “fullName
”selectedLanguage
property of the LanguageKeeperFinally, bind selectedLanguageISOName
on the LanguageKeeper to the appropriate property of the User Defaults Controller. (You can't bind the pop-up button directly to the UDC because the pop-up button needs one of your model objects.)
You could also try binding the pop-up button's content binding to the isoName
s and content-values binding to the fullName
s of the dictionaries in the array, but I'm very distrustful of using primitive objects as model objects. I've had too many problems from that in the past. Besides, using model objects pays off in the long run, and they're much fun to work with.
So with all of the above in place, here's what happens:
User changes the value in the pop-up buttonselectedLanguage
property of the LanguageKeeper.selectedLanguageISOName
) of the LanguageKeeper.selectedLanguageISOName
property of the LanguageKeeper.selectedLanguage
) of the LanguageKeeper.fullName
in the pop-up menu.If you don't understand any part of this answer, please ask for clarification.
Upvotes: 1