My application has to poll a server for a maximum of 10 minutes (using RestKit), even if the application is sent to the background. (polling always starts while the application is in the foreground)
I have a View Controller (not the RootViewController) that listens to applicationDidEnterBackground.
Also, there’s a class “Order” that has a method “poll” which is used to send a request to the server, and several other callback methods for “timeout”, “request cancel”, “handle response”, etc.
- (void)poll
{
RKRequest* request = [[RKClient sharedClient] requestWithResourcePath:@"/foo.php" delegate:self];
request.backgroundPolicy = RKRequestBackgroundPolicyContinue;
[request send];
NSLog(@"I am your RKClient singleton : %@", [RKClient sharedClient]);
}
- (void)requestDidStartLoad:(RKRequest *)request {
NSLog(@"requestDidStartLoad");
}
- (void)requestDidTimeout:(RKRequest *)request {
NSLog(@"requestDidTimeout");
}
- (void)request:(RKRequest *)request didFailLoadWithError:(NSError *)error {
NSLog(@"didFailLoadWithError");
}
- (void)request:(RKRequest*)request didLoadResponse:(RKResponse*)response
{
}
While the app is in the foreground, everything works fine and the callbacks are triggered.
When my application enters the background i want to continue polling the server. I use this method, “poll” is called, but no callbacks are triggered..
- (void)applicationDidEnterBackground:(NSNotification *) notification
{
Order *order = [[Order alloc] init];
UIApplication *app = [UIApplication sharedApplication];
__block UIBackgroundTaskIdentifier taskId;
taskId = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:taskId];
}];
if (taskId == UIBackgroundTaskInvalid) {
return;
}
dispatch_async(dispatch_get_global_queue(0, 0), ^{
while(YES)
{
sleep(1);
[order poll];
}
[app endBackgroundTask:taskId];
});
[order release];
}
What am I doing wrong?
I don’t know this RKClient you’re using but probably it’s based on NSURLConnection API. This asynchronous API calls delegates only if it’s running inside a run-loop; from NSURLConnection documentation:
Unfortunately GCD doesn’t guarantee you to run a block inside a thread which executes a run-loop. The suggestion in such case is that you run your “poll” inside a NSOperation which is optimized for this kind of situations.