Guy S
Guy S

Reputation: 1424

how to check why NSXMLParser initWithContentsOfURL method is taking too long?

I send an update to my server every 5 seconds with a timer. In response I receive an XML from the server which I parse using NSXMLParser. MyParser is set as the delegate and implements the needed callbacks to parse the document (including - (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError). most of the time the parsing is successful but every few minutes initWithContentsOfURL gets stuck for about a minute (almost exactly one minute avery time), then [parser parse] returns false and after that i keep getting successful parsing till the next failure.

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:5
                                                  target:self
                                                selector:@selector(parseDocument)
                                                userInfo:nil
                                                 repeats:YES];

- (void) parseDocument {
    dispatch_async(queue, ^{

        NSLog(@"before NSXMLParser alloc");
        NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:[[NSURL alloc] initWithString:@"https://secure.xxxxxxxxxxxxxxxxxxxxxx.dbm?xxxxxxxxxxxxxxxxxxxx"]];
        NSLog(@"after NSXMLParser alloc");

        MyParser *myParser = [[MyParser alloc] initParser:4];
        [parser setDelegate:myParser];
        BOOL result = [parser parse];
        if (result) {
            NSLog(@"Successful parse");
        } else {
            NSLog(@"Failed parse");
        }
    });
}

My question is how can I check why the parse (which fails) is taking about a minute and than returns false???

parseErrorOccurred is never called.

I checked the server side and everything is working and running as it should.

Any ideas????

Thanks in advance

EDIT:

As it turns out, [parser parse] is working fine, the problem occurs in initWithContentsOfURL , every few minutes this line takes one minute (instead of 1-2 second) than the parse returns false.

i checked server side if everything is ok within that minute and it looks fine. also checked if parser is not nil, which it isn't.

any suggestions on how to check whats causing the problem every few minutes in this line: NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:[[NSURL alloc] initWithString:@"https://secure.xxxxxxx.dbm?xxxxxxxxxx"]];, will be very appreciated.

Thanks

Upvotes: 1

Views: 626

Answers (1)

Tommy
Tommy

Reputation: 100632

Switch to an asynchronous fetch that explicitly alerts you upon a communications error: NSURLSession if under 7 or later, the appropriate class method of NSURLConnection if support for 6 is required. Either way you'll end up with an NSError, an NSData and an NSURLResponse, which you can cast to NSHTTPURLResponse to check for a 200 response code.

If there's no error, a valid response code and greater-than-zero length data, proceed to hand the data to an NSXMLParser.

EDIT: so, I'm on a real computer now (rather than an iPad) and therefore can add that I'd gravitate towards code like:

[[[NSURLSession sharedSession]
    dataTaskWithURL:[NSURL URLWithString:@"https://secure.xxxxxxxxxxxxxxxxxxxxxx.dbm?xxxxxxxxxxxxxxxxxxxx"]
    completionHandler:
    ^(NSData *data, NSURLResponse *response, NSError *error)
    {
        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;

        if(httpResponse.statusCode != 200 || error || ![data length])
        {
            NSLog(@"Some error condition");
            return;
        }

        NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
        [parser setDelegate:myParser];
        BOOL result = [parser parse];
        if (result) {
            NSLog(@"Successful parse");
        } else {
            NSLog(@"Failed parse");
        }
    }] resume];

I've favoured NSURLSession even though I'm just then telling the returned task to resume and never using any of the improved functionality over NSURLConnection's asynchronous mechanism, such as cancellation, because it is anecdotally much better at caching and because it'll automatically ensure an appropriate place is found to accumulate results and ultimately dispatch the completion handler asynchronously. So that's a few lines saved.

Upvotes: 3

Related Questions