0

我创建了一个NSMutableArray调用tempArray来保存我想要的三个元素的字符。目前,当我设置断点并让解析器运行时,tempArray每次都会正确更改,并为我提供所需的信息(纬度、经度、名称)。

然后,当解析器调用didEndElement...“a-location”的方法时,我添加tempArray到 main NSMutableArraynamed parsedNearMe,它应该包含所有 a-locations(每个都有名称、纬度、经度)。

这一切都按预期工作。

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

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

我尝试或研究但没有运气的可能解决方案- 以 某种方式清除指针,以便我可以重用tempArray(或重新初始化它?) - 每次动态创建一个新名称tempArray(不要认为在 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];
    }
}
4

1 回答 1

1

有几个问题:

  1. didEndElementfor设置以日期为键的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

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

- (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 文件中项目的顺序。如果您要使用字典来处理任何事情,我会在这里使用它。

所以,底线,而不是值是数组的字典,我会翻转它。我建议使用一组字典对象。我认为parsedNearMe应该是一个NSMutableArray。而不是被NSMutableArray调用tempArray,你应该使用NSMutableDictionary被调用tempDictionary

首先,定义几个 ivars:

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;
    }
}
于 2013-09-28T02:24:59.863 回答