0

I have a dictionary which I am storing in another dictionary, which itself gets stored in an array, like so:

NSMutableDictionary* sectionHeights = [[NSMutableDictionary alloc]initWithObjectsAndKeys:
                [NSString stringWithFormat:@"%f", section1Height], @"Section 1 Height",
                [NSString stringWithFormat:@"%f", section2Height], @"Section 2 Height",
        nil];

        [sectionObjects addObject:
         [[NSMutableDictionary alloc] initWithObjectsAndKeys:
          @"Site Inspection Report", @"Form Name",
          @"2", @"Section Count",
          sectionHeights, @"Section Heights",
          nil]
         ];

I pass the array to a property value of another class. When I try to read back sectionHeights, like so, the app crashes:

//get the subSectionData
    NSDictionary* subSectionData = [sectionObjects objectAtIndex:sectionObjects.count-1];
    NSDictionary* sectionHeights = [subSectionData objectForKey:@"Section Heights"];
    for(id obj in sectionHeights) {
        NSLog(@"%@", obj);
    }

in this case sectionHeights has 2 objects, NSStrings which will get converted to floats, but looking at the console output it seems as if the app is trying to output 3 objects:

2012-11-01 10:59:26.338 OAI_Accordion[2402:c07] Section 1 Height
2012-11-01 10:59:26.339 OAI_Accordion[2402:c07] Section 2 Height
2012-11-01 10:59:26.340 OAI_Accordion[2402:c07] -[__NSCFConstantString countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance 0x9088
2012-11-01 10:59:26.341 OAI_Accordion[2402:c07] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFConstantString countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance 0x9088'
*** First throw call stack:
(0x1c95012 0x10d2e7e 0x1d204bd 0x1c84bbc 0x1c8494e 0x46e8 0x2c84 0xfb817 0xfb882 0x4aa25 0x4adbf 0x4af55 0x53f67 0x225b 0x177b7 0x17da7 0x18fab 0x2a315 0x2b24b 0x1ccf8 0x1bf0df9 0x1bf0ad0 0x1c0abf5 0x1c0a962 0x1c3bbb6 0x1c3af44 0x1c3ae1b 0x187da 0x1a65c 0x1e9d 0x1dc5 0x1)
libc++abi.dylib: terminate called throwing an exception

I can't see where I am setting it up wrong so I was hoping extra sets of eyes on it might help.

PruitIgoe
  • 6,166
  • 16
  • 70
  • 137
  • Can you paste the code where you call `countByEnumeratingWithState:objects:count:`? Are you implementing `` protocol anywhere? – Rok Jarc Nov 01 '12 at 15:21
  • That's the thing, I'm not calling that anywhere, the for(id obj in sectionHeights) is the only place I am enumerating/looping through the dictionary – PruitIgoe Nov 01 '12 at 15:23
  • It looks like the error happens somewhere after that loop. You could try a NSLog or breakpoint to see if it loops trough normally. – Rok Jarc Nov 01 '12 at 15:26
  • It's happening because of the loop, if I delete the loop the app runs fine. – PruitIgoe Nov 01 '12 at 15:29
  • Try NSLog the sectionHeights before the for loop, see if there is 3 objects in there. – mashdup Nov 01 '12 at 15:29
  • I tried your code on an template project and it doesn't crash - it really looks that problem occours later. – Rok Jarc Nov 01 '12 at 15:37
  • 1
    Try this ['debugging recipe'](http://stackoverflow.com/questions/1163981/how-to-add-a-breakpoint-to-objc-exception-throw) - you might get some more info on the origin of the problem. – Rok Jarc Nov 01 '12 at 15:58
  • 1
    Solved it, there are 5 sections, it was happening further down, too long to explain but I wasn't passing the right data. Thanks for the help. – PruitIgoe Nov 01 '12 at 16:46

2 Answers2

2

It looks like your application is crashing because of the loop:

for(id obj in sectionHeights) {
    NSLog(@"%@", obj);
}

Which is most likely why you're getting the error countByEnumeratingWithState:objects:count: as you're trying to loop through a dictionary of values incorrectly.

You could loop through your dictionary using enumeration via a block as such:

[sectionHeights enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop)
{
    //
    NSLog(@"key: %@ -> value: %@", key, obj);
}];

This gives you access to the dictionary keys and values side by side. Your previous implementation crashes as the compiler doesn't know what to do with a dictionary in the context you have provided.

If you prefer the syntax of fast enumeration, you should loop through the array of dictionary values (or keys if you need them instead) by changing your code to:

for(id obj in [sectionHeights allValues]) {
    NSLog(@"%@", obj);
}

You can also use [sectionHeights allKeys] if you need the dictionary keys instead.

Zack Brown
  • 5,990
  • 2
  • 41
  • 54
  • I tried both solutions and it still crashed. (But I did learn something from your post so thanks for that). To me it still seems like it is trying to enumerate/loop through 3 items instead of the two that are there. If you look at the console I outputted in the OP you can see the two values are logged before it crashes. – PruitIgoe Nov 01 '12 at 16:05
  • +1 for good post. though i don't think this will solve OP's problem - the posted code does not cause a crash - tested. – Rok Jarc Nov 01 '12 at 16:38
1

Please, try this:

NSDictionary* subSectionData = [sectionObjects objectAtIndex:sectionObjects.count-1];
NSDictionary* sectionHeights = [subSectionData objectForKey:@"Section Heights"];

for(id obj in [sectionHeights allValues]) {
    NSLog(@"%@", obj);
}
sergio
  • 68,819
  • 11
  • 102
  • 123