Using the correct answer by Simon Whitaker, I was able to build a hierarchy of constants by embedding a Dictionary in a Dictionary in a Dictionary. Below is example source code, modified from my real source code.
This is a real-world problem-solution. In my particular case, the goal was organizing the strings that identify products accessed via StoreKit for In-App Purchase in Apple's App Store for iOS. Imagine our app presents content from a pair of books, one on cats, the other dogs. Furthermore, our app sells an abridged version of the content as well as unabridged. Upgrading from the abridged to the unabridged means a third product, "upgrade". Each pair of books might be translated, in this case English and Italian.
Looking at the strings I'm trying to track, you might think "Why doesn't that guy just use the strings themselves rather than going through this KVC nonsense?". Well, notice the 2nd string, English > Cats > Unabridged. The string ends with an appended underscore. That's because when I used iTunesConnect to create the In-App Purchase products, I accidentally created that item as "Consumable" instead of "Non-Consumable". Apple does not allow changing the ID, even if you delete said product. So the original string could not be used; alternatively, I appended the underscore as a workaround. So the point is, these strings are arbitrary and messy.
Another similar need for this approach would by if these string values might occasionally change at compile-time, so you don't want to be copy-pasting into more than one place in your source-code. A hierarchy of constants, in other words.
Inside Xcode, I want a better way of referring to these product identifiers.
// Using new literals syntax in later versions of Xcode 4 (& 5) to declare and populate a dictionary nested in a dictionary also in a dictionary.
NSDictionary *productIdentifiersHierarchy = @{
@"en" : @{
@"cats" : @{
@"abridged" : @"com.example.My_App.cats_abridged_en",
@"unabridged" : @"com.example.My_App.cats_unabridged_en_",
@"upgrade" : @"com.example.My_App.cats_upgrade_en"
},
@"dogs" : @{
@"abridged" : @"com.example.My_App.dogs_abridged_en",
@"unabridged" : @"com.example.My_App.dogs_unabridged_en",
@"upgrade" : @"com.example.My_App.dogs_upgrade_en"
}
},
@"it" : @{
@"cats" : @{
@"abridged" : @"com.example.My_App.cats_abridged_it",
@"unabridged" : @"com.example.My_App.cats_unabridged_it",
@"upgrade" : @"com.example.My_App.cats_upgrade_it"
},
@"dogs" : @{
@"abridged" : @"com.example.My_App.dogs_abridged_it",
@"unabridged" : @"com.example.My_App.dogs_unabridged_it",
@"upgrade" : @"com.example.My_App.dogs_upgrade_it"
}
}
};
Here's how to access these triple-nested dictionaries.
// Use KVC (Key-Value Coding) as a convenient way to access the nested dictionary structure.
NSLog( [productIdentifiersHierarchy valueForKeyPath:@"en.cats.abridged"],
NSLog( [productIdentifiersHierarchy valueForKeyPath:@"en.cats.unabridged"],
NSLog( [productIdentifiersHierarchy valueForKeyPath:@"en.cats.upgrade"],
NSLog( [productIdentifiersHierarchy valueForKeyPath:@"en.dogs.abridged"],
NSLog( [productIdentifiersHierarchy valueForKeyPath:@"en.dogs.unabridged"],
NSLog( [productIdentifiersHierarchy valueForKeyPath:@"en.dogs.upgrade"],
NSLog( [productIdentifiersHierarchy valueForKeyPath:@"it.cats.abridged"],
NSLog( [productIdentifiersHierarchy valueForKeyPath:@"it.cats.unabridged"],
NSLog( [productIdentifiersHierarchy valueForKeyPath:@"it.cats.upgrade"],
NSLog( [productIdentifiersHierarchy valueForKeyPath:@"it.dogs.abridged"] );
NSLog( [productIdentifiersHierarchy valueForKeyPath:@"it.dogs.unabridged"] );
NSLog( [productIdentifiersHierarchy valueForKeyPath:@"it.dogs.upgrade"] );