Background transfers are a new feature of iOS 7 where you can have the OS download files in the background and have them ready for your application when you launch it the next time. In this episode we write a simple image downloader that takes advantage of background sessions.
UPDATE: A keen subscriber pointed out that there is a bug in the code presented in the video preventing the download from completing in the background. The fix was to create the background NSURLSession lazily so that it is not only created after the download button is pressed. I've updated the code on Github and the notes here. Thanks, @eallam! Episode Links Episode Source Code URL Loading System Programming Guide Creating a background session We lazily create it via the getter method so that it is created on demand. - (NSURLSession *)session { if (!_session) { NSURLSessionConfiguration *config = [NSURLSessionConfiguration backgroundSessionConfiguration:@"your-unique-session-id-here"]; _session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil]; } return _session; } When using the background session configuration, you must use the session delegate methods, not the blocks. Handling background transfer events We have to start by listening on the app delegate to the event that lets us know the background transfer is about to be completed. - (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler { NSDictionary *userInfo = @{@"sessionIdentifier": identifier, @"completionHandler": completionHandler}; [[NSNotificationCenter defaultCenter] postNotificationName:@"BackgroundSessionUpdated" object:nil userInfo:userInfo]; } Here we just grab the session identifier that this download is for and the completion handler and raise a simple notification. In our view controller we handle this notification... - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleBackgroundSession:) name:@"BackgroundSessionUpdated" object:nil]; } - (void)handleBackgroundSession:(NSNotification *)notification { if ([notification.userInfo[@"sessionIdentifier"] isEqualToString:self.session.configuration.identifier]) { self.backgroundCompletionHandler = notification.userInfo[@"completionHandler"]; } } ... and we simply save the completion block. Once the download has completed, it will call the normal delegate methods and end with a call to: - (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session { if (self.backgroundCompletionHandler) { self.backgroundCompletionHandler(); self.backgroundCompletionHandler = nil; } }