title: How to Update UIProgressView to Display NSUrlSession Download Progress After Changing View Controller
body: <p>I have a ViewController on which the user can tap a button and start a relatively large download (around 200mb). I have all the correct NSUrlSession delegates in place, and as long the user does not navigate away from the ViewController, a UIProgressView will update perfectly and everything downloads just fine. My problem is that while the file is downloading, I want the user to be able to go to other ViewControllers, but still be able to come back and check the progress of the download.</p>
  
  <p>However, after navigating to a different ViewController and coming back, the delegate methods are not firing for the download task. I can tell with NSLog that the file is still downloading, but the UIProgressView no longer updates because the delegate methods aren't being called. How, when coming back to the page can I grab the currently running download task and fire its delegate methods in order to correctly update the progress view?</p>
  
  <p>When I navigate to the Download File page, I set up the NSUrlSession.</p>
  
  <pre><code>- (void)viewDidLoad
  {
      [super viewDidLoad];
  
      // Create a session with the custom configuration
      self.session = [self backgroundSession];
  }
  
  - (NSURLSession *)backgroundSession
  {
      static NSURLSession *session = nil;
      static dispatch_once_t onceToken;
      dispatch_once(&amp;onceToken,
                ^{
                    // Session Configuration
                    NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfiguration:@"com.NSUrlSession.app"];
  
                    // Initialize Session
                    session = [NSURLSession sessionWithConfiguration:sessionConfiguration
                                                            delegate:self
                                                       delegateQueue:nil];
                });
  
      return session;
  }
  </code></pre>
  
  <p>Then I have a button that creates the download task and starts downloading.</p>
  
  <pre><code>- (IBAction)downloadMovie:(id)sender
  {
      [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
  
      NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:LARGE_MOVIE]];
  
      NSURLSessionDownloadTask *task = [self.session downloadTaskWithRequest:request];
  
      [task resume];
  }
  </code></pre>
  
  <p>Here is the delegate method that updates the UIProgressView</p>
  
  <pre><code>- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
  {
      double progress = (double) (totalBytesWritten/1024) / (double) (totalBytesExpectedToWrite/1024);
      dispatch_async(dispatch_get_main_queue(),
                     ^{
                         [self.progressView setProgress:progress animated:NO];
                         NSLog(@"%f", progress);
                     });
  }
  </code></pre>
  
  <p>Like I said, as long as the user doesn't navigate to a different view controller everything downloads perfectly and the UIProgressView updates correctly. But, if the user leaves and comes back, the the newly instantiated view controller isn't the same as the original one that was assigned as the delegate to the session, so the delegate method isn't firing and its not updating the UIProgressView, even though the file is still downloading in the background as you can tell from the NSLog updates.</p>