Question

Given this P-List Dictionary:

enter image description here

How do I get at the 3rd. Key - "Dinner" - which in itself is also a Dictionary, and parse its values correctly?

Or, should I structure this P-List differently to begin with, so I can get at everything more easily?

Here's what I got, starting by grabbing all the Keys from my 'MenuDictionary' and storing them in an Array:

// Load the Property-List file into the Dictionary:
MenuDictionary = [[NSDictionary alloc] initWithContentsOfFile:menuPath];

// Get all the Keys from the Dictionary, put 'em into a 'mealTimesArray':
mealTimesArray = [[MenuDictionary allKeys] sortedArrayUsingSelector:@selector(compare:)];

// For each meal-type KEY, grab all the Values (dishes) in it and store them in a 'mealDishesArray':
for (NSString *mealTime in mealTimesArray) {
    NSArray *mealDishesArray = [MenuDictionary valueForKey:mealTime];

    // Now I can iterate through the 'mealDishesArray' to access each dish at
    // a time, so I can print them out or do whatever else:
    for (NSString *dish in mealDishesArray) {
        NSLog(@"Iterating through 'mealDishesArray' now...");
        NSLog(@"Current 'dish' is: %@", dish);

The problem occurs when I get to the "Dinner" key: its a Dictionary, containing 2 Keys with 2 array Values. So how do I load its contents into a Dictionary object? More specifically, what 'init' method should I be using to load the "Dinner" contents into my new Dictionary object?

I tried this - doesn't work:

// I put this inside the first fast-enum loop:

if ([mealTime isEqualToString: @"Dinner"]) {
   // init new Dictionary object (declared previously):
   dinnerDictionary = [[NSDictionary alloc] initWith ???];

I'd like to init it with the contents of the "Dinner" Key, but its not a P-List file obviously, so I can't use

   initWithContentsOfFile: pathName

I don't understand which of the other init methods will give me access to both the Keys and Values of "Dinner". Because even though "Dinner" is structured as a Dictionary, its currently sitting inside an Array, which doesn't regard it as a Dictionary (I think...)

I'm a little unclear about this obviously.

Or, should I be structuring my P-List differently to begin with so I can get at this nested Dinner dictionary?

Any ideas?

Was it helpful?

Solution

I think plist structure makes sense, and dealing with the contents conditionally based on class is perfectly okay, too. I would react to what's in the plist within a reasonable range of expectations, so...

// for each meal...
for (NSString *mealTime in mealTimesArray) {
    // we're not sure what kind of meal we have
    id mealInfo = [MenuDictionary valueForKey:mealTime];

    if ([id isKindOfClass:[NSArray self]]) {
        // it's an array? cast as an array and deal with the array
        NSArray *mealDishesArray = (NSArray *)mealInfo;
        [self handleMealArray:mealDishesArray];
    } else if ([id isKindOfClass:[NSDictionary self]]) {
        // it's a dictionary?  that's cool, too. cast as a dictionary and deal with it
        NSDictionary *mealDictionary = (NSDictionary *)mealInfo;
        [self handleMealDictionary:mealDictionary];
    }
}

// you've worked out to handle the array
- (void)handleMealArray:(NSArray *)mealDishesArray {
    for (NSString *dish in mealDishesArray) {
        NSLog(@"Iterating through 'mealDishesArray' now...");
        NSLog(@"Current 'dish' is: %@", dish);
    }
}

// handle the dictionary like a dictionary, realizing that it contains
// arrays, which you've already worked out how to handle
- (void)handleMealDictionary:(NSDictionary *)mealDictionary {
    for (NSString *dishType in [mealDictionary allKeys]) {
        NSArray *mealDishesArray = [mealDictionary valueForKey:dishType];
        [self handleMealArray:mealDishesArray];
    }
}

OTHER TIPS

The 'problem' is with this line:

NSArray *mealDishesArray = [MenuDictionary valueForKey:mealTime];

when mealTime is 'Dinner' you are assigning mealDishesArray a value that is an NSDictionary. Thinking you have an array you then use:

for (NSString *dish in mealDishesArray)

to iterate over the elements in the array which is not going to give you what you expect for 'Dinner'. You might consider adding something like:

NSAssert ([mailDishesArray isKindOfClass: [NSArray class]], @"Expecting an array");

after your assignment to mealDishesArray.

What is the solution? Your PLIST has a totally different structure between 'Breakfast,' 'Lunch,' and 'Dinner.' Why is 'Dinner' a NSDictionary and the others are NSArray? Make them all the same type. If they can't be, then you must conditionalize your code based on:

if ([mealTime isEqualToString: @"Dinner"]) {
   NSDictionary *dinnerDictionary = (NSDictionary *) [MenuDictionary valueForKey:mealTime];
   /* ... */ }

You don't need to alloc anything or read anything from file; you already have a dictionary for the 'Dinner' data.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top