title: NSURLSession downloadTask not releasing memory
body: <p>Due to the customer can't implement just few downloads in his server in a short time and backgroundDownloadTaks were very inconsistent when there are so much files (500-1000 downloads) I decide to use NSURLDownloadTask without background NSURLSession.</p>
  
  <p>It works quite well with a large amount of files, but there is an inconvenience. Memory usage is always growing untill I get a memory warning. When I get it I cancel pending tasks and free NSURLCache but memory is not released so when you resume the downloads you get the same memory warning.</p>
  
  <p>I'm not using cancelWithResumeData for cancelling the tasks.</p>
  
  <p>This is my code</p>
  
  <pre><code>- (void) startDownloadFiles:(NSMutableArray*)arrayFiles
  {
      if([[UIDevice currentDevice] isMultitaskingSupported])
      {
          dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  
              if (!self.session)
              {
                  NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
                  sessionConfiguration.HTTPMaximumConnectionsPerHost = 5;
                  sessionConfiguration.timeoutIntervalForRequest = 0;
                  sessionConfiguration.timeoutIntervalForResource = 0;
                  sessionConfiguration.requestCachePolicy = NSURLCacheStorageNotAllowed;
  
                  self.session = [NSURLSession sessionWithConfiguration:sessionConfiguration
                                                               delegate:self
                                                          delegateQueue:nil];
  
              }
  
              //Resetting session
              [self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
  
                  for (NSURLSessionTask *_task in downloadTasks)
                  {
                      [_task cancel];
                  }
  
                  [self.session resetWithCompletionHandler:^{                       
                      for (id&lt;FFDownloadFileProtocol&gt; file in self.selectedCatalogProducto.downloadInfo.arrayFiles)
                      {
                          if (cancel)
                              break; //Do not create more taks                        
  
                          if (![file isDownloaded])
                              [self startDownloadFile:file];
  
                      }                
                  }];
  
              }];
  
          });
  
      }
  }
  
  
  - (void) startDownloadFile:(id&lt;FFDownloadFileProtocol&gt;)file
  {
      if (![file isDownloading])
      {
          if ([file taskIdentifier] == -1
              &amp;&amp; ! cancel)
          {
              NSURLSessionDownloadTask *task = [self.session downloadTaskWithURL:[file downloadSource]];
  
              if (task)
              {
                  [file setDownloadTask:task];
                  [file setTaskIdentifier:[file downloadTask].taskIdentifier];
                  [[file downloadTask] resume];
              }
              else
              {
                  NSLog(@"Error creando tarea para descargar %@", [file downloadSource]);
              }
          }
      }
  }
  
  #pragma mark - Auxiliar Methods
  
  -(id&lt;FFDownloadFileProtocol&gt;)getFileDownloadInfoIndexWithTaskIdentifier:(unsigned long)taskIdentifier
  {
      for (id&lt;FFDownloadFileProtocol&gt; file in self.selectedCatalogProducto.downloadInfo.arrayFiles)
      {
          if (file.taskIdentifier == taskIdentifier) {
              return file;
          }
      }
  
      return nil;
  }
  
  #pragma mark - NSURLSessionDownloadTaskDelegate
  
  - (void) URLSession:(NSURLSession *)session
         downloadTask:(NSURLSessionDownloadTask *)downloadTask
         didWriteData:(int64_t)bytesWritten
    totalBytesWritten:(int64_t)totalBytesWritten
  totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
  {
      if (totalBytesExpectedToWrite == NSURLSessionTransferSizeUnknown) {
          NSLog(@"Unknown transfer size");
      }
      else
      {
          // Locate the FileDownloadInfo object among all based on the taskIdentifier property of the task.
          id&lt;FFDownloadFileProtocol&gt; file = [self getFileDownloadInfoIndexWithTaskIdentifier:downloadTask.taskIdentifier];
          // Calculate the progress.
          file.downloadProgress = (double)totalBytesWritten / (double)totalBytesExpectedToWrite;
  //        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
  //            NSLog("%@ ; %f", [file fileName], [file downloadProgress]);
  //        }];
      }
  }
  
  - (void)URLSession:(NSURLSession *)session
        downloadTask:(NSURLSessionDownloadTask *)downloadTask
  didFinishDownloadingToURL:(NSURL *)location
  {
      id&lt;FFDownloadFileProtocol&gt; file = [self getFileDownloadInfoIndexWithTaskIdentifier:downloadTask.taskIdentifier];
  
      if (file)
      {
          NSError *error;
          NSFileManager *fileManager = [NSFileManager defaultManager];
  
          NSURL *destinationURL = [[NSURL fileURLWithPath:tempPath] URLByAppendingPathComponent:[file fileName]];
  
          if ([fileManager fileExistsAtPath:[destinationURL path]]) {
  
              NSError *delError = nil;
              [fileManager removeItemAtURL:destinationURL error:nil];
  
              if (delError)
              {
                  NSLog(@"Error borrando archivo temporal en %@", [destinationURL path]);
              }
  
          }
  
          BOOL success = [fileManager copyItemAtURL:location
                                              toURL:destinationURL
                                              error:&amp;error];
  
          if (success) {
  
              // Change the flag values of the respective FileDownloadInfo object.
  
              file.isDownloading = NO;
              file.isDownloaded = YES;
  
              // Set the initial value to the taskIdentifier property of the file object,
              // so when the start button gets tapped again to start over the file download.
  
          }
          else
          {
              NSLog(@"Unable to copy temp file to %@ Error: %@", [destinationURL path], [error localizedDescription]);
          }
  
          if ([[UIApplication sharedApplication] applicationState] == UIApplicationStateActive)
          {
              indexFile++;
              [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                  [self numFilesDownloaded:indexFile];
              }];
          }
      }
  }
  
  - (void)URLSession:(NSURLSession *)session
                task:(NSURLSessionTask *)task
  didCompleteWithError:(NSError *)error
  {
      id&lt;FFDownloadFileProtocol&gt; file = [self getFileDownloadInfoIndexWithTaskIdentifier:task.taskIdentifier];
  
      if (error != nil
          &amp;&amp; error.code != -999)
      {
          //No se ha producido error o se ha cancelado la tarea bajo demanda
          [[NSOperationQueue mainQueue] addOperationWithBlock:^{
  
              NSLog(@"Download: %@. \n Downlonad completed with error: %@", [task.response.URL absoluteString], [error localizedDescription]);
  
              if (!cancel)
              {
                  NSString *alertBody = @"Se ha producido un error en la descarga, por favor reanúdela manualmente";
  
                  if ([error.domain isEqualToString:@"NSPOSIXErrorDomain"] &amp;&amp; (error.code == 1) )
                  {
                      alertBody = @"Se ha interrumpido la descarga debido a que su iPad está bloqueado por código. Por favor reanude la descarga manualmente y evite que el iPad se bloquee";
                  }
  
                  // Show a local notification when all downloads are over.
                  UILocalNotification *localNotification = [[UILocalNotification alloc] init];
                  localNotification.alertBody = alertBody;
                  [[UIApplication sharedApplication] presentLocalNotificationNow:localNotification];
  
                  [self errorDownloading:error.localizedDescription];
              }
          }];
  
      }
      else if (file)
      {
          NSLog(@"%@ download finished successfully.", [[file downloadSource] absoluteString]);
  
          file.taskIdentifier = -1;
  
          // In case there is any resume data stored in the file object, just make it nil.
          file.taskResumeData = nil;
          file.downloadTask = nil;
      }
      else if (cancel)
      {
          NSLog(@"Tarea cancelada");
      }
  
      if (self.selectedCatalogProducto.downloadInfo.arrayFiles.count == indexFile
          &amp;&amp; !cancel)
      {
          [[NSOperationQueue mainQueue] addOperationWithBlock:^{
              if (!complete)
              {
                  complete = YES;
                  [self downloadComplete];
              }
          }];
      }
  
      task = nil;
  }
  
  #pragma mark - Memory warning
  
  - (void)didReceiveMemoryWarning
  {
      [super didReceiveMemoryWarning];
  
      if (_isDownloading)
      {
          [self storeCatalogProductInfo:self.selectedCatalogProducto andDownloadInfo:YES];
          [self stopDownloading];
      }
  
      [[NSURLCache sharedURLCache] removeAllCachedResponses];
      [self.session.configuration.URLCache removeAllCachedResponses];
  }
  </code></pre>
  
  <p>And these are two snapshot of memory usage</p>
  
  <p><img src="https://i.stack.imgur.com/6YNPN.png" alt="Memory usage increasing when files are downloading">
  Memory usage increasing when files are downloading</p>
  
  <p><img src="https://i.stack.imgur.com/iLxZB.png" alt="Download tasks are stopped but memory is not released">
  Download tasks are stopped but memory is not released</p>
  
  <p>Why can't I release memory?</p>
  
  <p>Thanks for any help provided</p>