如何使用NSXMLParser提高性能

时间:2014-08-01 14:56:07

标签: objective-c parsing nsxmlparser

我正在处理大型xml文件,需要下载并解析他。在65k对象内部,但解析时间更长。我无法理解如何优化加载/解析,请帮我提供建议。另外,由于工作周期长,需要大量内存而且我不知道如何减少内存消耗。

 AFXMLRequestOperation *operation = [AFXMLRequestOperation 
    XMLParserRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, NSXMLParser *XMLParser) {
                XMLParser.delegate = delegate;
                [XMLParser parse];

                if (delegate.done) {
                    NSLog(@"done");
                }
            } failure:nil];
            [operation start];

- (void)parserDidStartDocument:(NSXMLParser *)parser {
    _done = NO;
    _items = [NSMutableArray new];

    _isItem = NO;
    _isPrice = NO;
    _isDetail = NO;
}

// parsing Ended
- (void)parserDidEndDocument:(NSXMLParser *)parser {
    _done = YES;
}

// if parsing error
-(void) parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
        _done = YES;
        _error = parseError;
}

// if validation error
-(void) parser:(NSXMLParser *)parser validationErrorOccurred:(NSError *)validationError {
    _done = YES;
    _error = validationError;
}
// new element to parse
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {

        if ([elementName isEqualToString:kItem]) {
            // если да - создаем строку в которую запишем его значение
            VZMenuItem *item = [[VZMenuItem alloc] init];
            _item = item;
            _item.name = attributeDict[@"name"];
            _item.code = attributeDict[@"code"];
            _isItem = YES;
            return;
        } else if ([elementName isEqualToString:kAttributes]) {
            VZRecipe *recipe = [[VZRecipe alloc] init];
            recipe.weight = [attributeDict[@"weight"] floatValue];
            recipe.sugar = [attributeDict[@"sugar"] floatValue];
            recipe.calories = [attributeDict[@"calories"] intValue];
            recipe.milk = [attributeDict[@"milk"] floatValue];
            recipe.eggs = [attributeDict[@"eggs"] unsignedIntValue];
            _item.recipe = recipe;
            return;
        } else if ([elementName isEqualToString:kPrice]) {
            _isPrice = YES;
            return;
        } else if ([elementName isEqualToString:kDetail]) {
            _isDetail = YES;
        }
}

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

        if ([elementName isEqualToString:kItem]) {
            [_items addObject:_item];
        }
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {

        if(_isPrice) {
            NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
            _item.price = [formatter numberFromString:string];
            _isPrice = NO;
        } else if(_isDetail) {
            _item.detailUrl = string;
            _isDetail = NO;
        }
}

CPU/Memory

1 个答案:

答案 0 :(得分:2)

您应该尝试从流中解析XML文件。您可以初始化NSXMLParser initWithStream:,它将NSInputStream作为参数,它将从流对象中批量读取和解析数据。

您可以使用initWithURL:创建NSInputStream,并传递下载xml文件的URL。当您使用流初始化NSXMLParser时,它将自动打开并读取流。

随着时间的推移,使用更少的内存并希望减少CPU,这会更频繁地为您提供更小的响应。

这种方法有一点点暗示: Apple说NSXMLParser打开流并开始阅读,但即使你打电话: [parser setDelegate:self]如果您不致电[parser parse],则不会调用委托方法。这里的诀窍是在GCD块中调用parse

 xmlParser = [[NSXMLParser alloc] initWithStream:inputStream];   [xmlParser setDelegate:self];
 dispatch_block_t dispatch_block = ^(void) {      
     [xmlParser parse];   
 };
dispatch_queue_t dispatch_queue = dispatch_queue_create("parser.queue", NULL);
dispatch_async(dispatch_queue, dispatch_block);   
dispatch_release(dispatch_queue);

希望它有所帮助。