2013-09-28 25 views
0

我创建了一个名为tempArrayNSMutableArray,它包含我想要的三个元素的字符。目前,当我设置断点并让解析器运行时,每次都会正确更改,并为我提供我需要的信息(纬度,经度,名称)。addObject覆盖的所有对象:使用NSXMLParser时

然后,当分析器呼吁“一个定位”的didEndElement...方法,我想补充tempArray名为parsedNearMe主要NSMutableArray,应保存所有的A位置(每个有名称,经纬度) 。

这一切都按预期工作。

问题: 每次我加tempArrayparsedNearMe,它增加了新的对象,而是将所有现有的对象到新对象的值。

我觉得是问题 我觉得现在的问题是,因为我需要的元素设置为tempArray,每一次我在覆盖每parsedNearMe对象,因为每个对象是指向同tempArray

可能的解决方案我已经尝试或没有运气研究 -Somehow清除指针,以便我可以重复使用tempArray(或重新初始化吗?) -dynamically代替每次tempArray创建一个新的名称(不要” t认为是可能的Objective-C)

我欣赏任何建议,因为我已经花了这么多小时在这已经做了圈子。此外,我会喜欢当前的架构工作(获取一个大数组数组,因此我可以调用1个数组并获取所需的所有数据)。

我的代码如下:

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict 
{ 

    if ([elementName isEqualToString:@"a-location"]) 
    { 
     if (!tempArray) 
      tempArray = [[NSMutableArray alloc] init]; 
     return; 
    } 


    if ([elementName isEqualToString:@"latitude"]) 
    { 
     latitude = [[NSMutableString alloc] init]; 
     return; 
    } 


    if ([elementName isEqualToString:@"longitude"]) { 
     longitude = [[NSMutableString alloc] init]; 
     return; 
    } 


    if ([elementName isEqualToString:@"the-name"]) { 
     myName = [[NSMutableString alloc] init]; 
     return; 
    } 

} 



-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string 
{ 
    currentString = [[NSMutableString alloc]init]; 
    [currentString appendString:string]; 

} 



- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName 
{ 

    if ([elementName isEqualToString:@"latitude"]) { 
     [tempArray addObject:currentString]; 
     return; 
    } 

    if ([elementName isEqualToString:@"longitude"]) { 
     [tempArray addObject:currentString]; 
     return; 
    } 

    if ([elementName isEqualToString:@"the-name"]) { 
     [tempArray addObject:currentString]; 
     return; 
    } 

    if ([elementName isEqualToString:@"a-location"]) 
    { 
     [parsedNearMe setObject:tempArray forKey:[NSDate date]]; 
     [tempArray removeAllObjects]; 
    } 
} 

回答

1

有几个问题:

  1. didEndElementa-location设定的日期键的值,但随后发生的指针点到同一个对象并删除该对象中的所有项目。因此,而不是:

    if ([elementName isEqualToString:@"a-location"]) 
    { 
        [parsedNearMe setObject:tempArray forKey:[NSDate date]]; 
        [tempArray removeAllObjects]; 
    } 
    

    你可能会替换成:

    if ([elementName isEqualToString:@"a-location"]) 
    { 
        [parsedNearMe setObject:tempArray forKey:[NSDate date]]; 
        tempArray = nil; // make sure you don't touch that object you just added to parsedNearMe 
    } 
    
  2. 我怀疑这个特殊的XML会存在这个问题,但是你foundCharacters认为,一个单一的通话将返回所有的数据。这不是一个有效的假设。有时需要多次调用。

  3. 您还有foundCharacters为您不感兴趣的XML部分追加字符串。除了解析纬度,经度和名称时,您应确保currentStringnil

所以,在最起码,我建议类似以下内容:每个字典由一些随机时间戳键控

- (void)parserDidStartDocument:(NSXMLParser *)parser 
{ 
    parsedNearMe = [[NSMutableDictionary alloc] init]; 
    currentString = nil; 
} 

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict 
{ 
    if ([elementName isEqualToString:@"a-location"]) 
    { 
     tempArray = [[NSMutableArray alloc] init]; 
    } 
    else if ([elementName isEqualToString:@"latitude"] || 
      [elementName isEqualToString:@"longitude"] || 
      [elementName isEqualToString:@"the-name"]) 
    { 
     currentString = [[NSMutableString alloc] init]; 
    } 
} 

-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string 
{ 
    [currentString appendString:string]; 
} 

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName 
{ 
    if ([elementName isEqualToString:@"latitude"] || 
     [elementName isEqualToString:@"longitude"] || 
     [elementName isEqualToString:@"the-name"]) 
    { 
     [tempArray addObject:currentString]; 
     currentString = nil; 
    } 
    else if ([elementName isEqualToString:@"a-location"]) 
    { 
     [parsedNearMe setObject:tempArray forKey:[NSDate date]]; 
     tempArray = nil; 
    } 
} 

这反映了当前的逻辑,创造词典,和值item是纬度,经度和名称的数组。

我个人认为,这样的设计从两个额外的缺陷所害,但:

  1. 你一些随机对象,[NSDate date]键控你的字典。这没有价值。你也可以使这个数组。您的经纬度和名称数组不明确。您的数据结构高度依赖于XML文件中项目的顺序。如果你打算使用任何字典,我会在这里使用它。

因此,底线,而不是字典的值是数组,我会翻转。我会建议一个字典对象的数组。我认为parsedNearMe应该是NSMutableArray。而代替NSMutableArraytempArray,你应该使用一个NSMutableDictionary称为tempDictionary

首先,定义了几个实例变量:

NSMutableArray *parsedNearMe;   // this was a NSMutableDictionary 
NSMutableDictionary *tempDictionary; 

然后你NSXMLParserDelegate程序可能看起来像:

- (void)parserDidStartDocument:(NSXMLParser *)parser 
{ 
    parsedNearMe = [[NSMutableArray alloc] init]; 
    currentString = nil; 
} 

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict 
{ 
    if ([elementName isEqualToString:@"a-location"]) 
    { 
     tempDictionary = [[NSMutableDictionary alloc] init]; 
    } 
    else if ([elementName isEqualToString:@"latitude"] || 
      [elementName isEqualToString:@"longitude"] || 
      [elementName isEqualToString:@"the-name"]) 
    { 
     currentString = [[NSMutableString alloc] init]; 
    } 
} 

-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string 
{ 
    [currentString appendString:string]; 
} 

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName 
{ 
    if ([elementName isEqualToString:@"latitude"] || 
     [elementName isEqualToString:@"longitude"] || 
     [elementName isEqualToString:@"the-name"]) 
    { 
     [tempDictionary setObject:currentString forKey:elementName]; 
     currentString = nil; 
    } 
    else if ([elementName isEqualToString:@"a-location"]) 
    { 
     [parsedNearMe addObject:tempDictionary]; 
     tempDictionary = nil; 
    } 
} 

或者,如果您想将NSNumber对象的经度和纬度存储为字符串,则可以将didEndElement替换为:

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName 
{ 
    if ([elementName isEqualToString:@"latitude"] || 
     [elementName isEqualToString:@"longitude"]) 
    { 
     [tempDictionary setObject:@([currentString doubleValue]) forKey:elementName]; 
     currentString = nil; 
    } 
    else if ([elementName isEqualToString:@"the-name"]) 
    { 
     [tempDictionary setObject:currentString forKey:elementName]; 
     currentString = nil; 
    } 
    else if ([elementName isEqualToString:@"a-location"]) 
    { 
     [parsedNearMe addObject:tempDictionary]; 
     tempDictionary = nil; 
    } 
} 
+0

结构非常好的答案,谢谢。 虽然我还没有尝试过你的解决方案,但我相信这将解决我的问题:tempArray = nil; 我也同意你的设计建议。实际上,我原本只有两个NSMutableArrays,但最终以当前的字典设计结束了,因为我只是想了很多方法,并且认为使用NSDictionary和键可以解决每次覆盖对象的问题。 – Joel

+0

此外,这也是为什么我试图把他们的关键随机日期。出于某种原因,我认为给它一个唯一的名字(日期)会阻止对象被覆盖。我也尝试在0开始一个计数器,并使用数字作为关键。感谢您清除这:)。 – Joel