title: Constantly growing memory allocation while fetching images over HTTP in iOS
body: <p>I am implementing an iOS App that needs to fetch a huge amount of images over HTTP. I've tried several approaches but independently what I do, Instuments shows constantly increasing memory allocations and the App crashes sooner or later when I run it on a device. There are no leaks shown by Instruments.</p>
  
  <p>So far I have tried the following approches:</p>
  
  <ul>
  <li>Fetch the images using a synchronous NSURLConnection within an NSOperation</li>
  <li>Fetch the images using a asynchronous NSURLConnection within an NSOperation</li>
  <li>Fetch the images using [NSData dataWithContentsOfURL:url] in the Main-Thread</li>
  <li>Fetch the images using synchronous ASIHTTPRequest within an NSOperation</li>
  <li>Fetch the images using asynchronous ASIHTTPRequest and adding it to a NSOperationQueue</li>
  <li>Fetch the images using asynchronous ASIHTTPRequest and using a completionBlock</li>
  </ul>
  
  <p>The Call Tree in Instrumetns shows that the memory is consumed while processing the HTTP-Response. In case of asynchronous NSURLConnection this is in</p>
  
  <pre><code>- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
  [receivedData appendData:data];
  }  
  </code></pre>
  
  <p>In case of the synchronous NSURLConnection, Instruments shows a growing CFData (store) entry.
  The problem with ASIHTTPRequest seems to be the same as with the asynchronous NSURLConnection in a analogous code-position. The [NSData dataWithContentsOfURL:url] approach shows an increasing amount of total memory allocation in exactely that statement.</p>
  
  <p>I am using an NSAutoReleasePool when the request is done in a separate thread and I have tried to free up memory with [[NSURLCache sharedURLCache] removeAllCachedResponses] - no success.</p>
  
  <p>Any ideas/hints to solve the problem? Thanks.</p>
  
  <p><strong>Edit:</strong>
  The behaviour only shows up if I persist the images using CoreData. Here is the code I run as a NSInvocationOperation:</p>
  
  <pre><code>-(void) _fetchAndSave:(NSString*) imageId {
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  NSString *url = [NSString stringWithFormat:@"%@%@", kImageUrl, imageId];
  HTTPResponse *response = [SimpleHTTPClient GET:url headerOrNil:nil];
  NSData *data = [response payload];
  
  if(data &amp;&amp; [data length] &gt; 0) {
      UIImage *thumbnailImage = [UIImage imageWithData:data];
      NSData *thumbnailData = UIImageJPEGRepresentation([thumbnailImage scaleToSize:CGSizeMake(55, 53)], 0.5); // UIImagePNGRepresentation(thumbnail); 
  
      [self performSelectorOnMainThread:@selector(_save:) withObject:[NSArray arrayWithObjects:imageId, data, thumbnailData, nil] waitUntilDone:NO];
  }
  [pool release];
  }
  </code></pre>
  
  <p>All CoreData related stuff is done in the Main-Thread here, so there should not be any CoreData multithreading issue. However, if I persist the images, Instruments shows constantely increasing memory allocations at the positions described above. </p>
  
  <p><strong>Edit II:</strong></p>
  
  <p>CoreData related code:</p>
  
  <pre><code>-(void) _save:(NSArray*)args {
  NSString *imageId = [args objectAtIndex:0];
  NSData *data = [args objectAtIndex:1];
  NSData *thumbnailData = [args objectAtIndex:2];
  
  Image *image = (Image*)[[CoreDataHelper sharedSingleton] createObject:@Image];
  image.timestamp =  [NSNumber numberWithDouble:[[NSDate date] timeIntervalSince1970]];
  image.data = data;
  
  Thumbnail *thumbnail = (Thumbnail*)[[CoreDataHelper sharedSingleton] createObject:@"Thumbnail"];
  thumbnail.data = thumbnailData;
  thumbnail.timestamp = image.timestamp;
  [[CoreDataHelper sharedSingleton] save];
  }
  </code></pre>
  
  <p>From CoreDataHelper (self.managedObjectContext is picking the NSManagedObjectContext usable in the current thread):</p>
  
  <pre><code>-(NSManagedObject *) createObject:(NSString *) entityName {
  return [NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:self.managedObjectContext];
  }
  </code></pre>