Is there a way to directly access an inner-array of an an outer array in Objective-C? For example, a call to an external data source returns the following object:
{
bio = "this is the profile.bio data";
"first_name" = John;
"last_name" = Doe;
location = {
name = "Any Town, Any State";
};
metadata = {
pictures = {
picture = "https://picture.mysite.com/picture.jpeg";
}
}
}
I want to be able to access, for example, the location.name or the metadata.pictures.picture data. Dot notation, however, does not seem to work. For example:
_gfbLocation = [result objectForKey:@"location.name"];
_gfbPicture = [result objectForKey:@"metadata.pictures.picture"];
The only way I have been able to access this data is by first setting the contents of the inner arrays to objects. Thoughts?
Access Nested Dictionary Items You can access individual items in a nested dictionary by specifying key in multiple square brackets. If you refer to a key that is not in the nested dictionary, an exception is raised. To avoid such exception, you can use the special dictionary get() method.
Create an empty NSMutableDictionary called 'shoeOrderDict'. NSMutableDictionary *shoeOrderDict = [[NSMutableDictionary alloc] init]; Now add the values in our array to our new dictionary. The keys for the values should be: 'customer', 'size', 'style' and 'color'.
Objective-C Quick Syntax Reference by NSDictionary is a class used to organize objects in lists using keys and values. NSDictionary can maintain an index of objects and let you retrieve an object if you have the right key.
Dictionaries can be nested to any depth. A dictionary can contain any object type except another dictionary. All the keys in a dictionary must be of the same type.
For nested keys like that you can use a keyPath. A keyPath is just a series of keys joined with dots. You can use them to retrieve nested values from objects that support Key-Value Coding - including NSDictionary objects like yours. So in your case this should work:
[result valueForKeyPath:@"location.name"];
For more detail on Key-Value Coding, see Apple's Key-Value Coding Programming Guide.
See also this related StackOverflow question.
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"] );
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