开发者

Setting progress of ProgressView while parsing XML

I am parsing using an XML file. I want to show a Progress Bar till the par开发者_开发技巧sing procedure completes. How can I calculate the progress of the ProgressView ?? Pls Help..


First, count the number of lines.

NSError *error = nil;
NSString *xmlFileString = [NSString stringWithContentsOfURL:url
                           encoding:NSUTF8StringEncoding error:&error];
_totalLines = [xmlFileString componentsSeparatedByString:@"\n"].count;

Then, catch the progress in delegate method block. For example:

- (void)parser:(NSXMLParser *)parser 
  didStartElement:(NSString *)elementName 
  namespaceURI:(NSString *)namespaceURI 
  qualifiedName:(NSString *)qName 
  attributes:(NSDictionary *)attributeDict
{
    [self.elementStack addObject:elementName];

    NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
    [mainQueue addOperationWithBlock:^{
        _progressView.progress = (CGFloat)[parser lineNumber] / (CGFloat)_totalLines;
    }];
}

Sample Project is Here:

https://github.com/weed/p120727_XMLParseProgress

Setting progress of ProgressView while parsing XML


If you are parsing with NSXMLParser and know the length of the file being parsed, you can approximate progress by calling lineNumber on your parser object to tell you how far through the file the parser is.

progressView.progress = (CGFloat)[parser lineNumber] / (CGFloat)totalLines;


I'm processing large files where it was taking several seconds to count how many lines there are in the file.

I came up with a more complex but faster solution:

  • map the contents of the file into virtual memory, using NSData. This is the fastest way to read a large file on OS X and iOS. It will be loaded into RAM if it's a small/medium sized file, but large files will only partially be loaded into RAM.
  • using grand central dispatch, fire off a background task to process the data in 10KB chunks, counting how many newlines are found.
  • fire off another grand central dispatch task to parse the same NSData object.
  • whenever a new tag is started, every half a second, check if the line counting has finished, and if so it updates the progress bar.

Mapping a file into virtual memory and then seraching for newline bytes is around 10x faster than any other method I could find, including some low level C choices. It takes a split second to count a file with 3 million lines on my SSD equiped mac.

Doing it on a background thread, in parallel with NSXMLParser on the same NSData object, ensures the file will not be read from the disk twice (unless the file is too big to fit in RAM).

Source code for this is here: https://github.com/abhibeckert/Speed-Limit/blob/master/Speed%20Limit/SLOSMImporter.m

Note: the code I posted will work on iOS 7 and OS X 10.9. It has only been tested on OS X 10.9. It could be modified fairly easily to work on older versions of the SDK, just build it and the compile errors should be easy to fix.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜