我正在处理大型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;
}
}
答案 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);
希望它有所帮助。