title: NSURLSessionDownloadTask concurrent downloads, also supported in app background, not working as expected
body: <p><strong>Requirement:</strong></p>
  
  <p>I have a view controller class, in which I am showing a collection view. In it for each cell I am checking if image already exists in local or not, if it does not exist then I am trying to download the image from server and showing the same.</p>
  
  <p><strong>Implementation:</strong></p>
  
  <p>Below is the code for the same:</p>
  
  <pre><code>- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
  {
      // retrieving associated product
      Products *aProduct = [self.fetchedResultsController objectAtIndexPath:indexPath];
  
      UICollectionViewCell* newCell = [self.collectionView dequeueReusableCellWithReuseIdentifier:kProductIconIdentifier forIndexPath:indexPath];
  
      // setup of image view and cell label
      UIImageView *cellImageView = (UIImageView *)[collectionView viewWithTag:kImageViewTag];
      cellImageView.contentMode = UIViewContentModeScaleAspectFill;
  
      UILabel *cellLabel = (UILabel *)[newCell viewWithTag:klabelTag];
  
      // assigning value to cell label and image view
      NSString *productImageLocalPath = aProduct.imageLocalPath;
      if ([[NSFileManager defaultManager] fileExistsAtPath:productImageLocalPath]) {
          // file exists at local path :-)
          // means less fun :-(
          cellImageView.image = [UIImage imageWithContentsOfFile:productImageLocalPath];
      }
      else
      {
          UIActivityIndicatorView *downloadActivityIndicator = (UIActivityIndicatorView *)[newCell viewWithTag:kActivityIndicator];
          downloadActivityIndicator.hidden = NO;
          [downloadActivityIndicator startAnimating];
  
          // file does not exist at local path :-(
          // means more fun :-)
          [self.sessionController setupAndStartDownloadTaskForProduct:aProduct withCompletionHandler:^(NSString * tempLocalPath){
              // download was successful
  
              NSData *imageData = [[NSData alloc] initWithContentsOfFile:tempLocalPath];
              [imageData writeToFile:productImageLocalPath atomically:YES];
  
              cellImageView.image = [UIImage imageWithData:imageData];
              [downloadActivityIndicator stopAnimating];
  
          } andFailureHandler:^{
              cellImageView.image = nil;
              [downloadActivityIndicator stopAnimating];
          }];
      }
  
      // setting values
      cellLabel.text = aProduct.imageName;
  
      return newCell;
  }
  </code></pre>
  
  <p>In session controller class, I have below method to start a new download task:</p>
  
  <pre><code>- (void)setupAndStartDownloadTaskForProduct:(Products *)aProduct withCompletionHandler:(DownloadedCompletionHandler)completionHandler andFailureHandler:(DownloadedFailureHandler)failureHandler
  {
      NSString *completeImagePath = [kBasePath stringByAppendingPathComponent:aProduct.imageRelativePath];
  
      NSURL *downloadURL = [NSURL URLWithString:completeImagePath];
  
      if (!self.session) {
          [self setUpSession];
      }
  
      NSURLRequest *downloadRequest = [NSURLRequest requestWithURL:downloadURL];
  
      NSURLSessionDownloadTask *downloadTask = [self.session downloadTaskWithRequest:downloadRequest];
  
      NSDictionary *downloadInfoDict = @{kSuccessHandlerKey: [completionHandler copy], kFailureHandlerKey: [failureHandler copy]};
  
      self.downloadTasks[@(downloadTask.taskIdentifier)] = downloadInfoDict;
  
      // resuming the download task
      [downloadTask resume];
  
  }
  </code></pre>
  
  <p>In above method I am storing successHandler and failureHandler block in a dictionary, mapping it with download task using its task identifier.</p>
  
  <p>Below is the implementation of didFinishDownloadingToURL method:</p>
  
  <pre><code>- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
  {
      dispatch_async(dispatch_get_main_queue(), ^{
          // invoking success block
          DownloadedCompletionHandler successCompletionHandler = self.downloadTasks[@(downloadTask.taskIdentifier)][kSuccessHandlerKey];
          successCompletionHandler([location path]);
  
          // removing download task key-value pair from dictionary
          [self.downloadTasks removeObjectForKey:@(downloadTask.taskIdentifier)];
      });
  }
  </code></pre>
  
  <p><strong>My problem is -</strong> sometimes in above method downloadTask returns a different identifier than the one initiated at setupAndStartDownloadTaskForProduct, because of which successCompletionHandler is obtained as nil, and app crashes when I try to invoke the handler block.</p>
  
  <p>Now my questions are:</p>
  
  <ol>
  <li><p>Why in didFinishDownloadingToURL I am getting a different identifier, than the one initiated at  setupAndStartDownloadTaskForProduct?</p></li>
  <li><p>If this is the expected behavior then what is the best way to implement my requirement?</p></li>
  </ol>