n_b n_b - 1 month ago 12
iOS Question

Cannot get background URL Session to return

I have tried and failed many times to get some inherited code to successfully send a background session request. When in the foreground, it works flawlessly, but in the background it will either never return, or, in some cases, receive a auth challenge.

The code to create the request is pretty boilerplate:

NSURLSessionConfiguration *sessionConfig =
[NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:identifier];
sessionConfig.sessionSendsLaunchEvents = true;
sessionConfig.discretionary = false;
sessionConfig.requestCachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
sessionConfig.timeoutIntervalForResource = 60 * 60 * 24; //One day. Default is 7 days!

/* Create session, and optionally set a NSURLSessionDelegate. */
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig
delegate:self
delegateQueue:[NSOperationQueue mainQueue]];

NSURLComponents *urlComponents = [NSURLComponents new];
urlComponents.scheme = @"https";
urlComponents.host = @"jsonplaceholder.typicode.com";
urlComponents.path = @"/posts/1";

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[urlComponents URL]];
request.HTTPMethod = @"PUT";

NSLog(@"Making request: %@", request);

/* Start a new Task */
NSURLSessionDataTask *task = [session dataTaskWithRequest:request];
[task resume];


But I never get anything back. I do have the required background modes (probably)

<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
<string>remote-notification</string>
</array>


and my delegate is delegating everything

<NSURLSessionDelegate, NSURLSessionDataDelegate,NSURLConnectionDataDelegate,NSURLConnectionDelegate,NSURLSessionTaskDelegate>


Any help would be appreciated- I'm pretty sure I'm missing just one line of code somewhere. I even went so far as to create a GitHub repo just to test this code out- it schedules a Local Notification to allow you to run the session task in the background.

GitHub repo for BackgroundSender

Rob Rob
Answer

In the app delegate's handleEventsForBackgroundURLSession, you are doing nothing with the completion handler. You should:

  • save copy of the completionHandler;

  • start the background NSURLSession with that identifier; and

  • when done handling all of the delegate methods, call the saved completion handler; we often do that in URLSessionDidFinishEventsForBackgroundURLSession.


By the way, you shouldn't use data tasks with background sessions. You generally should use a download or upload task.


Also, those background modes are not necessary for background NSURLSession. Background fetch is designed for a different problem, namely periodically polling to see if your server has data available. If you need that, then by all means, use the fetch background mode, but realize that this is a separate topic from merely performing background requests.

See Fetching Small Amounts of Content Opportunistically in the App Programming Guide for iOS: Background Execution for a discussion of background fetch, and compare that to the Downloading Content in the Background section.

Likewise, the remote-notification key is unrelated, too. As the docs say, remote-notification is used when "The app wants to start downloading content when a push notification arrives. Use this notification to minimize the delay in showing content related to the push notification."