recursion遍历未知结构的NSDictionary
有没有人做过一个未知结构的NSDictionaryrecursion遍历? 我想采取任何NSDictionary,并按层次顺序处理每个级别。
1)这些数据来自validation的JSON。 可以肯定地说,从SBJSON(JSON Framework)这样的框架创build的NSDictionary只会导致嵌套的字典,数组和任意叶子的组合?
2)如何使用适用于数组和字典的快速枚举来进行generics遍历? 用下面的代码,一旦我得到一个数组中的字典,它停止遍历。 但是,如果我在数组条件中继续recursion(以检查数组中的字典),它会在下一次id value = [dict valueForKey:key];
迭代中使用bar id value = [dict valueForKey:key];
与-[__NSCFDictionary length]: unrecognized selector sent to instance
SIGABRT。 我不知道为什么这会是一个问题,因为我已经通过顶级字典(其中发现了子级字典数组)的那一行。
-(void)processParsedObject:(id)dict counter:(int)i parent:(NSString *)parent { for (id key in dict) { id value = [dict valueForKey:key]; NSLog(@"%i : %@ : %@ -> %@", i, [value class], parent, key); if ([value isKindOfClass:[NSDictionary class]]) { i++; NSDictionary* newDict = (NSDictionary*)value; [self processParsedObject:newDict counter:i parent:(NSString*)key]; i--; } else if ([value isKindOfClass:[NSArray class]]) { for (id obj in value) { NSLog(@"Obj Type: %@", [obj class]); } } } }
非常感谢
我做了类似的事情,我将遍历来自Web服务的JSON结构化对象,并将每个元素转换为可变版本。
- (void)processParsedObject:(id)object { [self processParsedObject:object depth:0 parent:nil]; } - (void)processParsedObject:(id)object depth:(int)depth parent:(id)parent { if ([object isKindOfClass:[NSDictionary class]]) { for (NSString* key in [object allKeys]) { id child = [object objectForKey:key]; [self processParsedObject:child depth:(depth + 1) parent:object]; } } else if ([object isKindOfClass:[NSArray class]]) { for (id child in object) { [self processParsedObject:child depth:(depth + 1) parent:object]; } } else { // This object is not a container you might be interested in it's value NSLog(@"Node: %@ depth: %d", [object description], depth); } }
我需要知道这些值的关键名字,所以我重写了Joel所写的,并提出了这个问题:
- (void)enumerateJSONToFindKeys:(id)object forKeyNamed:(NSString *)keyName { if ([object isKindOfClass:[NSDictionary class]]) { // If it's a dictionary, enumerate it and pass in each key value to check [object enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) { [self enumerateJSONToFindKeys:value forKeyNamed:key]; }]; } else if ([object isKindOfClass:[NSArray class]]) { // If it's an array, pass in the objects of the array to check [object enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { [self enumerateJSONToFindKeys:obj forKeyNamed:nil]; }]; } else { // If we got here (ie it's not a dictionary or array) so its a key/value that we needed NSLog(@"We found key %@ with value %@", keyName, object); } }
然后你会这样称呼它:
[self enumerateJSONToFindKeys:JSON forKeyNamed:nil];
另外,如果你想让一个给定的键path可变(所以你可以使用setValue:forKeyPath:
写),你可以做如下的事情:
- (void)makeDictionariesMutableForKeyPath:(NSString *)keyPath { NSArray *keys = [keyPath componentsSeparatedByString:@"."]; NSString *currentKeyPath = nil; for (NSString *key in keys) { if (currentKeyPath) { NSString *nextKeyPathAddition = [NSString stringWithFormat:@".%@", key]; currentKeyPath = [currentKeyPath stringByAppendingString:nextKeyPathAddition]; } else { currentKeyPath = key; } id value = [self.mutableDictionary valueForKeyPath:currentKeyPath]; if ([value isKindOfClass:NSDictionary.class]) { NSMutableDictionary *mutableCopy = [(NSDictionary *)value mutableCopy]; [self.mutableDictionary setValue:mutableCopy forKeyPath:currentKeyPath]; } } }