addObject覆盖的所有对象:使用NSXMLParser时

时间:2013-09-28 01:55:21

标签: ios objective-c nsmutablearray nsxmlparser

我创建了一个名为NSMutableArray的{​​{1}},其中包含我想要的三个元素的字符。目前,当我设置断点并让解析器运行时,tempArray每次都会正确更改,并为我提供所需的信息(纬度,经度,名称)。

然后,当解析器调用" a-location"的tempArray方法时,我将didEndElement...添加到名为tempArray的主NSMutableArray,它应该包含所有的a位置(每个位置都有名称,纬度,经度)。

这一切都按预期工作。

问题: 每次我将parsedNearMe添加到tempArray时,它都会添加新对象,但会将所有现有对象设置为新对象的值。

我认为问题是什么 我认为问题在于,因为我将当前元素设置为parsedNearMe,并且每次我都覆盖tempArray中的每个对象,因为每个对象都是指向同一个{{1}的指针}}

我尝试或研究的可能解决方案没有运气 - 以某种方式清除指针,以便我可以重用parsedNearMe(或重新初始化它?) - 每次动态创建一个新名称代替tempArray(在Objective-C中不可能认为)

我感谢任何建议,因为我花了这么多时间在这上面我已经在做圈子了。此外,我有点像当前的架构工作(获得一个大型数组,所以我可以调用其中一个数组并获得该注释所需的所有数据)。

我的代码如下:

tempArray

1 个答案:

答案 0 :(得分:1)

有几个问题:

  1. didEndElement a-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

  4. 所以,至少,我建议如下:

    - (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;
        }
    }
    

    这反映了您当前的逻辑,创建了一些随机时间戳键入的字典,每个字典项的值是纬度,经度和名称的数组。

    就个人而言,我认为这个设计还有两个额外的缺陷:

    1. 您通过一些随机对象[NSDate date]来键入字典。这没有任何价值。你不妨把它变成一个数组。

    2. 您的纬度,经度和名称数组不明确。您的数据结构高度依赖于XML文件中项目的顺序。如果您打算使用字典,我会在这里使用它。

    3. 所以,底线,而不是一个值为数组的字典,我会翻转它。我建议一组字典对象。我认为parsedNearMe应该是NSMutableArray。而不是名为NSMutableArray的{​​{1}},您应使用名为tempArray的{​​{1}}:

      首先,定义一些ivars:

      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