views:

672

answers:

3

Hello, in my app I have a section where I load from a saved plist which has 2 nested dictionaries like this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
<plist version="1.0">
<dict>
    <key>1</key>
    <dict>
        <key>color</key>
        <string>yellow</string>
        <key>lang</key>
        <string>US</string>
        <key>name</key>
        <string>Peter</string>
        <key>uid</key>
        <string>1</string>
    </dict>
    <key>2</key>
    <dict>
        <key>color</key>
        <string>blue</string>
        <key>lang</key>
        <string>US</string>
        <key>name</key>
        <string>Josh</string>
        <key>uid</key>
        <string>2</string>
    </dict>
    <key>3</key>
    <dict>
        <key>color</key>
        <string>red</string>
        <key>lang</key>
        <string>DE</string>
        <key>name</key>
        <string>Susan</string>
        <key>uid</key>
        <string>3</string>
    </dict>
</dict>
</plist>

Now I want to access string like outer dictionary from key 2, value for inner key color (blue) I tried make 2 loops, and it works for the outer dictionary but I can't access the inner

NSMutableDictionary *savedData = [NSMutableDictionary dictionaryWithContentsOfFile:path]; // This contains all data from plist

for (int x=0; x<[savedData count]; x++) {
    NSString *itemNumber = [NSString stringWithFormat:@"%d", x+1];

    //This prints out the correct inner dictionary
    NSLog(@"item#%@: %@",itemNumber,[savedData objectForKey:itemNumber]);


    for (NSDictionary *dict in [savedData objectForKey:itemNumber]) {
        //prints out color, lang, uid, but no key-value pairs 
        NSLog(@"dict: %@",dict);
    }
}

I'd like to know how to directly access key value pairs inside the inner dictionary, could anyone give me a kick in the right direction, please?

+1  A: 

Hey

How about this:

NSString *blueColorString = [[savedData objectForKey:@"2"] objectForKey:@"color"];

The trick is to nest the method calls, the first one [savedData objectForKey:2] returns you the inner dictionary object on which you can call the method again. Hope this works as intended.

Best, Robin

Robin
It can be so easy, I didn't think about that - thanks alot :)
hecta
@Robin: the key must be a string, even if it is the number 2 in the property list file.
benzado
@benzado: Hmm, just curious, how would the file be built then if it were an integer?
Robin
@Robin plist format requires keys to be strings. You can't have an integer key.
Dave DeLong
As Dave said Property List dictionaries may only have strings as keys. NSDictionary in general may have (almost) any object as a key, though it must be an object. So 2 is no good, but [NSNumber numberWithInt:2] would be OK.
benzado
A: 

Typically, you would use valueForKey: when your keys are strings:

// to get to "blue" string
NSLog(@"outer key '2', inner key 'color' = %@",[[savedData valueForKey:@"2"] valueForKey:@"color"]);

// all inner key / value pairs
for (NSString *key in savedData) {
    NSDictionary *innerDict = [savedData valueForKey:key];

    for (NSString *innerKey in innerDict) {
        NSLog(@"key %@ value %@",innerKey,[innerDict valueForKey:innerKey]);
    }
}
gerry3
Thank you as well
hecta
A: 

NSLog(@"%@", [savedData valueForKeyPath:@"1.color"]);

yellow

nst
That's even more elegant than the previous answers, thank you
hecta