Достижение самого глубокого дочернего уровня в NSDictionary - PullRequest
7 голосов
/ 14 мая 2011

У меня есть объект NSDictionary с глубокими структурами, такими как массивы, содержащие дополнительный массив, который содержит словари ...

Я хочу получить объект в иерархии. Есть ли какой-нибудь способ прямого индексирования, чтобы получить их, используя имена ключей или что-то еще?

Больно продолжать вызывать методы objectForKey несколько раз, чтобы достичь самого глубокого дочернего уровня.

Ответы [ 3 ]

7 голосов
/ 14 мая 2011

Если вы используете только словари и если ключи в ваших словарях всегда являются строками, вы можете использовать кодирование значения ключа для обхода нескольких уровней словарей:

id someObject = [mainDictionary valueForKey:@"apple.pear.orange.bear"];

Это эквивалентно:

NSDictionary *level2Dict = [mainDictionary objectForKey:@"apple"];
NSDictionary *level3Dict = [level2Dict objectForKey:@"pear"];
NSDictionary *level4Dict = [level3Dict objectForKey:@"orange"];
id someObject = [level4Dict objectForKey:@"bear"];

Однако это не очень удобно, если в миксе также есть массивы.См. это недавнее обсуждение SO для получения дополнительной информации по этой теме.

4 голосов
/ 14 мая 2011

Для структуры, включающей массивы, не существует встроенного способа сделать что-то вроде:

[dict objectForKey:@"[level1][level2][level3]"]

При этом все встроенное - это просто код, написанный кем-то в Apple, и вы можете сделать то же самое.

Напишите вспомогательный класс, который сделает это за вас на основе созданной вами схемы объединения ключей, а затем просто вызовите его. Это сохранит дублирование кода.

3 голосов
/ 03 октября 2012
//
//  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);
...