Reputation: 1424
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
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