how to iterate nested dictionaries in objective-c iphone sdk
Hi I have a json string converted unsing the JSON framework into a dictionary and I need to extract its content. How could I iterate to the nested dictionaries? I have already this code that allows me to see the dictionary:
NSDictionary *results = [responseString JSONValue];
NSMutableArray *catArray = [NSMutableArray array];
for (id key in results) {
NSLog(@"key: %@, value: %@", key, [results objectForKey:key]);
[catArray addObject:k开发者_如何学运维ey];
NSString *cat = key;
}
Could someone provide a sample on how to get to all the levels of the dic not using the name of the keys?
The result structure of the dic is like this: http://www.freeimagehosting.net/uploads/e7c020d697.png
alt text http://www.freeimagehosting.net/uploads/e7c020d697.png
thanks
ldj
You probably have to try recursive function.
-(void)recurse:(NSDictionary *)dict counter: (int*) i parent:(NSString *) parent{
for (NSString* key in [dict allKeys]) {
id value = [dict objectForKey:key];
NSLog(@"%@ -> %@", parent, key);
if ([value isKindOfClass:[NSDictionary class]]) {
i++;
NSDictionary* newDict = (NSDictionary*)value;
[self recurse:newDict counter:i parent:key];
i--;
} else {
//Do smthg
}
}
}
this will list all keys and its level.
Try
for ((id) key in [results allKeys]) {
NSLog(@"key: %@, value: %@", key, [results objectForKey:key]);
[catArray addObject:key];
NSString *cat = key;
}
Hope that helped.
EDIT: i'm not sure if i understand your structure correct, but i'm asuming you have some values in your dictionairy which are again dictionairies. if you want to interate through a dictionairy which is located inside another one you could do it like this:
for ((id) key in [results allKeys]) {
id value = [results objectForKey:key];
if ([value isKindOfClass:[NSDictionary class]]) {
NSDictionary* newDict = (NSDictionary*)value;
for ((id) subKey in [newDict allKeys]) {
...
}
}
}
Of couse if you know the specific key to your desired dictionairy, you can check for that instead of checking if the value is a dict. But maybe it's not a bad idea to check that in both cases...
I'm sure you have solved this at this point, but I found it convenient to write a recursive utility class function that recursively logs every key of a dictionary:
/**
* Recursively logs the keys and values of each object in the dictionary,
* along with the class of the value.
*
* @param dict The dictionary to inspect
*/
+ (void)logDictionaryKeys:(NSDictionary*)dict {
for (id key in dict) {
if ([dict[key] isKindOfClass:[NSDictionary class]]) {
[self logDictionaryKeys:dict[key]];
}else {
NSLog(@"Key: %@", key);
NSLog(@"Value: %@ (%@)", dict[key], [dict[key] class]);
}
}
return;
}
The header of the category:
#import <Foundation/Foundation.h>
@interface NSDictionary(Find)
-(id) findflat:(NSString*)keyToFind;
@end
The body:
#import "NSDictionary+Find.h"
@implementation NSDictionary(Find)
-(id) findflat:(NSString*)keyToFind{
if([self objectForKey:keyToFind])
return self[keyToFind];
for(id key in self)
if([[self objectForKey:key] isKindOfClass:[NSDictionary class]])
return [[self objectForKey:key] findflat:keyToFind];
return nil;
}
@end
Usage/Validation:
- (void)testExample {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
NSDictionary *dic = @{};
XCTAssertNil([dic findflat:@"url"]);
dic = @{@"url":@"http://"};
XCTAssertEqual([dic findflat:@"url"],@"http://");
dic = @{@"other":@4};
XCTAssertNil([dic findflat:@"url"]);
dic = @{@"other":@4,@"url":@"http://"};
XCTAssertEqual([dic findflat:@"url"],@"http://");
dic = @{@"other":@4,@"sd":@"sdf"};
XCTAssertNil([dic findflat:@"url"]);
dic = @{@"other":@4,@"dic":@{@"url":@"http://"}};
XCTAssertEqual([dic findflat:@"url"],@"http://");
dic = @{@"other":@4,@"dic":@{@"sd":@2,@"url":@"http://"}};
XCTAssertEqual([dic findflat:@"url"],@"http://");
dic = @{@"other":@4,@"dic":@{}};
XCTAssertNil([dic findflat:@"url"]);
dic = @{@"other":@4,@"dic":@{@"dic":@{@"sd":@2,@"url":@"http://"}}};
XCTAssertEqual([dic findflat:@"url"],@"http://");
}
I have tried recursion and hope this could help.
P.S. This will return the first occurrence of the key.
+(id)getValue:(NSDictionary*)aDictionary forKey:(NSString *)aKey {
id finalValue = nil;
for (id key in [aDictionary allKeys]) {
id value = aDictionary[key];
if (value != nil && [key isEqualToString:aKey]) {
finalValue = value;
break;
}
else if ([value isKindOfClass:[NSDictionary class]]) {
finalValue = [[self class] getValue:value forKey:aKey];
}
}
return finalValue;
}
精彩评论