I have an iOS 5 app that uses NSURLConnection to load some XML via GET. On very rare occasions connections appear to get stuck in a condition where they timeout repeatedly.
An example request:
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:url]];
/*
The request is set with a timeout interval of 10 because (due to the nature of
the app and the XML feed) this data is reloaded every 15 seconds.
*/
[request setTimeoutInterval:10];
[request setCachePolicy:NSURLRequestReloadIgnoringCacheData];
[request setHTTPMethod:@"GET"];
self.afOperation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
self.afOperation.successCallbackQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,0);
self.afOperation.failureCallbackQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,0);
//snip success/completion block code
[self.afOperation start];
So far I’ve seen three “recovery” scenarios when the requests begin to hang.
- Quit the entire app
- Plug the device into a computer (yes, really). Right after the iPhone/iPad acknowledges the connection it will immediately stop timing out.
- Leave the app and go do something else for awhile. Quickly leaving and reentering the app is typically insufficient to cause recovery.
As you might imagine, I find this incredibly bizarre. At this time I’ve replaced my own NSURLConnectionDelegate implementation with AFNetworking (as seen above) and am still running into the same problem. I’ve added logging to every NSURLConnectionDelegate protocol selector and found that the only selector called (after calling start) is connection:didFailWithError:. I’ve ensured I’m not piling up multiple requests (the previous request is always canceled and nil’d before starting a new one). Additionally, I’ve verified that no request is actually being sent via tcpdump on my router. What could cause this type of behavior?
It turns out this problem is caused by the TestFlight SDK v1.0 and below. See Why does NSURLConnection fail to reach the backend?
Until they release a fix there’s no way to workaround the problem short of stripping out the SDK entirely.