I am having a hard time trying to create and populate on the fly an NSMutableDictionary from a tree like structure.
我很难尝试从树状结构中动态创建和填充NSMutableDictionary。
Let's say you have a node where
假设你有一个节点在哪里
node.attributes
retrieves an NSArray
of key/value pairs
node.attributes检索键/值对的NSArray
and
node.children
retrieves an NSArray
of nodes from the same node type
node.children从同一节点类型中检索节点的NSArray
how can you convert that tree into a nested NSMutableDictionary
?
如何将该树转换为嵌套的NSMutableDictionary?
my aproach is to try to create a NSMutableDictionary
for each node and populate it with its attributes and children, creating a new NSMutableDictionary
per child and iterate again with it... it sounds like recursion, isn't it
我的方法是尝试为每个节点创建一个NSMutableDictionary,并用它的属性和子节点填充它,为每个子节点创建一个新的NSMutableDictionary并再次使用它迭代......听起来像递归,不是吗
The following code works, for one level deep (parent and children) but throw SIGABRT for grandchildren and beyond.
以下代码适用于一级深度(父级和子级),但为孙子孙后代抛出SIGABRT。
[self parseElement:doc.rootElement svgObject:&svgData];
where
-(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];
}
}
UPDATE:
thanks for your answers, I managed to do the code to work
谢谢你的回答,我设法让代码工作
apparently GDataXMLElement doesn't respond to attributeForName when there is no atributes and so my code threw some exeptions, that where dificult to debug being a recursive method
显然GDataXMLElement在没有属性的情况下不响应attributeForName,因此我的代码抛出了一些exeptions,其中dificult调试是一个递归方法
I am taking into account all your (best practice related) sugestions too
我也考虑了你所有(最佳实践相关)的消化
Regards
1 个解决方案
#1
1
Please note that I replaced your double indirections by a simple pointer. The only case I know where pointers to pointers make sense is in the connection with NSError. I would rewrite this part of code:
请注意,我用一个简单的指针替换了你的双重间接。我知道指针指针的唯一情况是与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];
}
}
If you don't trust in the magic behind implicit retains, just read what Apple tells you about the setObject:forKey:
如果你不相信隐式保留背后的魔力,只需阅读Apple告诉你的关于setObject的内容:forKey:
- (void)setObject:(id)anObject forKey:(id)aKey Parameters
(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: Forgot about your first part:
编辑:忘了你的第一部分:
NSMutableDictionary* svgData = [[NSMutableDictionary dictionary];
[self parseElement:doc.rootElement svgObject:svgData];
#1
1
Please note that I replaced your double indirections by a simple pointer. The only case I know where pointers to pointers make sense is in the connection with NSError. I would rewrite this part of code:
请注意,我用一个简单的指针替换了你的双重间接。我知道指针指针的唯一情况是与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];
}
}
If you don't trust in the magic behind implicit retains, just read what Apple tells you about the setObject:forKey:
如果你不相信隐式保留背后的魔力,只需阅读Apple告诉你的关于setObject的内容:forKey:
- (void)setObject:(id)anObject forKey:(id)aKey Parameters
(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: Forgot about your first part:
编辑:忘了你的第一部分:
NSMutableDictionary* svgData = [[NSMutableDictionary dictionary];
[self parseElement:doc.rootElement svgObject:svgData];