I'm trying to set up a download using NSURLSession
that will continue in the background.
I have a singleton class called DownloadManager
which builds the NSURLSession
and starts a download task like this:
- (id)init
{
self = [super init];
if (self) {
self.queue = [[NSOperationQueue alloc] init];
self.queue.maxConcurrentOperationCount = 1;
// Initialize the background session.
self.session = [self backgroundSession];
}
return self;
}
- (NSURLSession *)backgroundSession
{
static NSURLSession *session = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfiguration:@"com.mycompany.myapp.BackgroundSession"];
session = [NSURLSession sessionWithConfiguration:sessionConfiguration
delegate:self
delegateQueue:self.queue];
});
return session;
}
- (void)startDownload:(Download *)download
{
NSURL *remoteURL = ...
NSURLSessionDownloadTask *task = [self.session downloadTaskWithURL:remoteURL];
[task resume];
}
I've implemented the NSURLSessionDelegate
and NSURLSessionDownloadDelegate
methods including URLSessionDidFinishEventsForBackgroundURLSession:
. Additionally, my application delegate implements application:handleEventsForBackgroundURLSession:completionHandler:
.
However, when I move my application to the background by pressing the home button after starting a download, all download delegate methods stop firing and application:handleEventsForBackgroundURLSession:completionHandler:
is never called. The download continues, and if I wait long enough for it to finish then URLSession:downloadTask:didFinishDownloadingToURL:
is called the moment I bring my app back to the foreground. This means that I can't do any post-processing in the background (e.g. save to core data, start a new download, etc.).
I tried adding the 'Background fetch' background mode to my plist in case that was required, and I tried changing my the identifier used to create the NSURLSessionConfiguration
background configuration as suggested in this answer. Have I made a mistake in setting this up, or am I not supposed to be able to handle download delegate events in the background?