开发者

NSDictionary for loop exception

I've a method with this part of code:

NSDictionary *tmpDict = [self getJsonDictionary];

NSInteger tmpID;

for (NSDictionary *d in tmpDict) {
    tmpID = [[d objectForKey:@"id"] integerValue];
}

tmpDict is a NSDictionary with variable size. If tmpDict contains at least 2 objects (2 NSDictionary) it works well but if it contains only 1 object (1 NSDictionary) throws this exception:

 -[NSCFString objectForKey:]: unrecognized selector sent to instance 0x4e866d0
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSCFString objectForKey:]: unrecognized selector sent to instance 0x4e866d0'

Why this? And how to fix if tmpDict has only 1 object?

Probably for (NSDictionary *d in tmpDict) is 开发者_如何转开发the problem and when tmpDict has 1 object d is a NSCFString, but why?

-- UPDATE

The problem is when tmpDict has 1 item (one NSDictionary) the for (NSDictionary *d in tmpDict) take every key/value item in the dictionary and this is the reason for exception. Otherwise if tmpDict has 2+ items is a NSDictionary of NSDictionary and it works well. I need a way to fix this still using the for loop. Ideas?

-- UPDATE 2*

Actually this code works but it's redundant:

if ([tmpObject isKindOfClass:[NSDictionary class]]) {
    tmpID = [[tmpObject objectForKey:@"id"] integerValue];
    tmpProp2 = [tmpObject objectForKey:@"prop2"];
    tmpProp3 = [tmpObject objectForKey:@"prop3"];
    tmpProp4 = [tmpObject objectForKey:@"prop4"];
} else if ([tmpObject isKindOfClass:[NSArray class]]) {
    for (NSDictionary *d in tmpObject) {
        tmpID = [[d objectForKey:@"id"] integerValue];
        tmpProp2 = [d objectForKey:@"prop2"];
        tmpProp3 = [d objectForKey:@"prop3"];
        tmpProp4 = [d objectForKey:@"prop4"];
    }
}

It needs an improvement.


I'm surprised it works at all actually. For dictionaries, fast enumeration enumerates the keys. That's why it's telling you that -objectForKey: has been sent to an NSCFString because the key of a dictionary coming from JSON is always a string.

You should, perhaps, do this:

for (id d in [tmpDict objectEnumerator])
{
    // Objects in a JSON dictionary aren't necessarily dictionaries
    if([d isKindOfClass:[NSDictionary class]])
    {
         tmpID = [[d objectForKey:@"id"] integerValue];
    }
}

One possible reason why it might work with two dictionaries is if the top level item is actually an array, not a dictionary. If you have:

[ { "id" : 1 }, { "id" : 2 } ]

your JSON parser will give you an NSArray, not an NSDictionary, which can be parsed with your code even though you assume your top level item is a dictionary.

Edit: Having seen your update, I'm sure this is what is happening. If you have one object, your JSON string is looking like:

{ "id" : 1, "prop2" : "value1", "prop3" : "value1", "prop4" : "value1" }

If you have two objects, it probably looks like:

[
        { "id" : 1, "prop2" : "value1", "prop3" : "value1", "prop4" : "value1" },
        { "id" : 2, "prop2" : "value1", "prop3" : "value1", "prop4" : "value1" }
]

Notice the square brackets, that means JSON array.


The error is occurring because there is an object of type NSString in your tmpDict variable, so you can use this.

 for (id *d in tmpDict)
{
    if([d isKindOfClass:[NSDictionary class]])
        tmpID = [[d objectForKey:@"id"] integerValue];
    else
        tmpID = [(NSString *)d intValue];
}

instead of this

for (NSDictionary *d in tmpDict) {
    tmpID = [[d objectForKey:@"id"] integerValue];
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜