This method sets the background object.
- (void) downloadWithURL: (NSMutableArray *)urlArray pathArr: (NSMutableArray *)pathArr mediaInfo: (MediaInfo *)mInfo { bgDownloadMediaInfo = mInfo; reqUrlCount = urlArray.count; dict = [NSDictionary dictionaryWithObjects:pathArr forKeys:urlArray]; mutableDictionary = [dict mutableCopy]; backgroundConfigurationObject = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"XXXXX"]; backgroundConfigurationObject.sessionSendsLaunchEvents = YES; backgroundConfigurationObject.discretionary = YES; backgroundSession = [NSURLSession sessionWithConfiguration: backgroundConfigurationObject delegate: self delegateQueue: [NSOperationQueue currentQueue]]; self.requestUrl = [urlArray objectAtIndex:0]; download = [backgroundSession downloadTaskWithURL:self.requestUrl]; [download resume]; }These are the completion handlers.
#pragma Mark - NSURLSessionDownloadDelegate - (void)URLSession: (NSURLSession *)session downloadTask: (NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL: (NSURL *)location { LogDebug(@"Download complete for request url (%@)", downloadTask.currentRequest.URL); NSString *temp = [mutableDictionary objectForKey:downloadTask.currentRequest.URL]; NSString *localPath = [NSString stringWithFormat: @"%@",temp]; NSFileManager *fileManager = [NSFileManager defaultManager]; NSURL *destinationURL = [NSURL fileURLWithPath: localPath]; NSError *error = nil; [fileManager moveItemAtURL:location toURL:destinationURL error:&error]; LogDebug(@"Moving download file at url : (%@) to : (%@)", downloadTask.currentRequest.URL, destinationURL); reqUrlCount --; downloadSegment ++; // Handover remaining download requests to the OS if ([finalUrlArr count] != 0) { // remove the request from the array that got downloaded. [finalUrlArr removeObjectAtIndex:0]; [finalPathArr removeObjectAtIndex:0]; if ([finalUrlArr count] > 0) { // proceed with the next request on top. self.requestUrl = [finalUrlArr objectAtIndex:0]; download = [backgroundSession downloadTaskWithURL:self.requestUrl]; [download resume]; } } if ([adsArray count] > 0) { adsArrayCount --; // delegate back once all the ADs segments have been downloaded. if (adsArrayCount == 0) { for (int i = 0; i < [adsArray count]; i++) { NSArray *ads = [adsArray objectAtIndex: i]; for (int j = 0; j < [ads count]; j++) { MediaInfo *ad = [ads objectAtIndex: j]; [self setDownloadComplete: ad]; // skip sending downloadFinish delegate if the media is marked as downloadDone if (!ad.downloadDone) { [delegate MediaDownloadDidFinish: ad.mediaId error: NO]; } ad.downloadDone = YES; } } downloadSegment = 0; } } // delegate back once all the main media segments have been downloaded. if (reqUrlCount == 0) { [self setDownloadComplete: mediaInfo]; state = DownloadState_Done; // skip sending downloadFinish delegate if the media is marked as downloadDone if (!bgDownloadMediaInfo.downloadDone) { [delegate MediaDownloadDidFinish: bgDownloadMediaInfo.mediaId error: NO]; } bgDownloadMediaInfo.downloadDone = YES; [urlArr release]; [pathArr release]; [finalUrlArr release]; [finalPathArr release]; // invalidate the NSURL session once complete [backgroundSession invalidateAndCancel]; } } - (void)URLSession: (NSURLSession *)session task: (NSURLSessionTask *)task didCompleteWithError: (NSError *)error { if (error) { NSLog(@"Failure to download request url (%@) with error (%@)", task.originalRequest.URL, error); } } - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite { // save the total downloaded size [self downloaderDidReceiveData:bytesWritten]; // enable the log only for debugging purpose. // LogDebug(@"totalBytesExpectedToWrite %llu, totalBytesWritten %llu, %@", totalBytesExpectedToWrite, totalBytesWritten, downloadTask.currentRequest.URL); }With out this code(beginBackgroundTaskWithExpirationHandler) the download stops when the app is pushed into background.
// AppDelegate_Phone.m - (void)applicationDidEnterBackground: (UIApplication *)application { NSLog(@"applicationDidEnterBackground"); UIApplication *app = [UIApplication sharedApplication]; UIBackgroundTaskIdentifier bgTask; bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ [app endBackgroundTask:bgTask]; }]; }