Создание и заполнение на лету вложенного NSMutatbleDictionary из древовидной структуры


Я с трудом пытаюсь создать и заполнить на лету NSMutableDictionary из древовидной структуры.

Допустим, у вас есть узел, где

node.attributes извлекает NSArray пар ключ / значение

И

node.children извлекает NSArray узлов из того же типа узла

Как можно преобразовать это дерево во вложенное NSMutableDictionary?

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

Следующий код работает, для одного уровня глубоко (родитель и дети), но бросить SIGABRT для внуков и за его пределами.

[self parseElement:doc.rootElement svgObject:&svgData];

Где

-(void) parseElement:(GDataXMLElement*)parent svgObject:(NSMutableDictionary**)svgObject
{
    NSLog(@"%@", parent.name);

    for (GDataXMLNode* attribute in parent.attributes)
    {
        [*svgObject setObject:attribute.stringValue forKey:attribute.name];
        NSLog(@"  %@ %@", attribute.name, attribute.stringValue);
    }

    NSLog(@"  children %d", parent.childCount);
    for (GDataXMLElement *child in parent.children) {
        NSLog(@"%@", child.name);

        NSMutableDictionary* element = [[[NSMutableDictionary alloc] initWithCapacity:0] retain];

        NSString* key = [child attributeForName:@"id"].stringValue;

        [*svgObject setObject:element forKey:key];
        [self parseElement:child svgObject:&element];
    }
}

Обновление:

Спасибо за ваши ответы, мне удалось сделать код для работы

По-видимому GDataXMLElement не реагирует на attributeForName, когда нет атрибутов, и поэтому мой код бросил некоторые exeptions, что где difficult to debug-рекурсивный метод

Я также принимаю во внимание все ваши (связанные с лучшей практикой) сугестионы

С уважением

1 2

1 ответ:

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

-(void) parseElement:(GDataXMLElement*)parent svgObject:(NSMutableDictionary*)svgObject
{

for (GDataXMLNode* attribute in parent.attributes)
{
    // setObject:forKey: retains the object. So we are sure it won't go away.
    [svgObject setObject:attribute.stringValue forKey:attribute.name];
}


for (GDataXMLElement *child in parent.children) {
    NSLog(@"%@", child.name);
    // Here you claim ownership with alloc, so you have to send it a balancing autorelease.
    NSMutableDictionary* element = [[[NSMutableDictionary alloc] init] autorelease];

    // You could also write [NSMutableDictionary dictionary];

    NSString* key = [child attributeForName:@"id"].stringValue;

    // Here your element is retained (implicitly again) so that it won't die until you let it.
    [svgObject setObject:element forKey:key];
    [self parseElement:child svgObject:element];
}

}

Если вы не доверяете магии, стоящей за неявными сохранениями, просто прочитайте, что Apple говорит вам о setObject: forKey:

  • (void)setObject: (id)anObject forKey: (id)aKey Parameters

AnObject

The value for key. The object receives a retain message before being added to the dictionary. This value must not be nil.

EDIT : забыл о своей первой части:

NSMutableDictionary* svgData = [[NSMutableDictionary dictionary];
[self parseElement:doc.rootElement svgObject:svgData];