Reputation: 38162
I have a NSDictionary object with deep structures in it like arrays containing further array which contain dictionaries...
I want to fetch an object down in the hierarchy. Is there any direct indexing way to fetch them using key names or something else?
Its a pain to keep on calling objectForKey methos multiple time to reach to deepest child level.
Upvotes: 8
Views: 3594
Reputation: 1092
//
// NSDictionary+Path.h
//
// Created by Wu Li-chih on 10/3/12.
// Copyright (c) 2012 Wu Li-chih. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSDictionary (Path)
- (id) objectForPath:(NSArray*)aKeyPath;
@end
//
// NSDictionary+Path.m
//
// Created by Wu Li-chih on 10/3/12.
// Copyright (c) 2012 Wu Li-chih. All rights reserved.
//
#import "NSDictionary+Path.h"
@implementation NSDictionary (Path)
- (id) objectForPath:(NSArray*)aKeyPath
{
if([d isKindOfClass:[NSDictionary class]])
d = [d objectForKey:aKey];
else if([d isKindOfClass:[NSArray class]])
d = [d objectAtIndex:[aKey integerValue]];
else
return nil;
if(d == nil)
return nil;
}
@end
// example
id v = [dict objectForPath:@[@"root", @"sub", @"target_node"]];
NSDictionary *a = @{ @"aaa" : @{ @"bbb": @[@123, @456, @{@"ccc": @"result"}]}};
id r = [a objectForPath:@[@"aaa", @"bbb", @2, @"ccc"]];
STAssertTrue([r isEqualToString:@"result"], nil);
r = [a objectForPath:@[@"aaa", @"bbb", @0, @"ccc"]];
STAssertNil(r, nil);
Upvotes: 3
Reputation: 33101
For a structure that includes Arrays, there is no built in way to do something like:
[dict objectForKey:@"[level1][level2][level3]"]
That being said, anything built in is just code that someone at Apple has written, and you can do the same.
Write a helper class that will do it for you based on a key concatenation scheme that you create, then just call it. It will save the code duplication.
Upvotes: 4
Reputation: 125007
If you're only using dictionaries, and if the keys in your dictionaries are always strings, you can use key-value coding to traverse several levels of dictionaries:
id someObject = [mainDictionary valueForKey:@"apple.pear.orange.bear"];
This is equivalent to:
NSDictionary *level2Dict = [mainDictionary objectForKey:@"apple"];
NSDictionary *level3Dict = [level2Dict objectForKey:@"pear"];
NSDictionary *level4Dict = [level3Dict objectForKey:@"orange"];
id someObject = [level4Dict objectForKey:@"bear"];
This isn't so convenient, though, if you also have arrays in the mix. See this recent SO discussion for more on this topic.
Upvotes: 8