Reputation: 7654
I have an app that receives silent pushes when it's inactive via the -[AppDelegate application:didReceiveRemoteNotification:fetchCompletionHandler:]
. The push payload contains a url that I need to prefetch so that the data is ready on next app start.
The app needs to call the completionHandler
when the downloads finishes:
The block to execute when the download operation is complete. When calling this block, pass in the fetch result value that best describes the results of your download operation. You must call this handler and should do so as soon as possible. For a list of possible values, see the UIBackgroundFetchResult type.
The question is whether I can do a simple NSURLSession
request or if I'm supposed to do the fetch using one of the background fetch as described here
Option 1: Use a simple NSURLSession
and call the callback
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler
{
NSURL *url = [NSURL URLWithString:userInfo[@"my-data-url"]];
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
NSURLSessionDataTask *task = [session dataTaskWithRequest:[NSURLRequest requestWithURL:url] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
// save the result & call the
completionHandler(data ? UIBackgroundFetchResultNewData : UIBackgroundFetchResultNoData);
}];
[task resume];
}
Option 2: Use extra background handling for downloading the content
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler
{
NSURLSessionDataTask *task;
__block UIBackgroundTaskIdentifier backgroundId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
// time's up, cancel the download
[application endBackgroundTask:backgroundId];
backgroundId = UIBackgroundTaskInvalid;
completionHandler(UIBackgroundFetchResultFailed);
[task cancel];
}];
NSURL *url = [NSURL URLWithString:userInfo[@"my-data-url"]];
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
task = [session dataTaskWithRequest:[NSURLRequest requestWithURL:url] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
// check if time was up
if(backgroundId == UIBackgroundTaskInvalid) {
return;
}
[application endBackgroundTask:backgroundId];
backgroundId = UIBackgroundTaskInvalid;
// save the result & call the
completionHandler(data ? UIBackgroundFetchResultNewData : UIBackgroundFetchResultNoData);
}];
[task resume];
}
Upvotes: 3
Views: 626
Reputation: 7654
So to answer my own question, after some testing, it appears the Option 2 works quite well. I can download whatever data I need using the UIBackgroundTaskIdentifier
. If I don't use it, the download fails
Upvotes: 3