在iOS中通过HTTP获取图像时不断增长的内存分配

我正在实现一个需要通过HTTP获取大量图像的iOS应用程序。 我已经尝试了几种方法,但独立我做什么,Instuments显示不断增加的内存分配和应用程序迟早崩溃,当我在设备上运行它。 仪器没有显示泄漏。

到目前为止,我已经尝试了以下几点:

  • 在NSOperation中使用同步NSURLConnection获取图像
  • 在NSOperation中使用asynchronousNSURLConnection获取图像
  • 在主线程中使用[NSData dataWithContentsOfURL:url]获取图像
  • 在NSOperation中使用同步ASIHTTPRequest获取图像
  • 使用asynchronousASIHTTPRequest获取图像并将其添加到NSOperationQueue
  • 使用asynchronousASIHTTPRequest并使用completionBlock获取图像

Instrumetns中的调用树显示内存在处理HTTP响应时被占用。 在asynchronousNSURLConnection的情况下,

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { [receivedData appendData:data]; } 

在同步NSURLConnection的情况下,Instruments显示一个正在增长的CFData(存储)条目。 ASIHTTPRequest的问题似乎与在类似的代码位置的asynchronousNSURLConnection相同。 这个[NSData dataWithContentsOfURL:url]方法显示了在exactely那个语句中增加的总内存分配量。

当请求在一个单独的线程完成时,我正在使用一个NSAutoReleasePool,我试图用[[NSURLCache sharedURLCache] removeAllCachedResponses]释放内存 – 没有成功。

任何想法/提示解决问题? 谢谢。

编辑:行为只显示如果我坚持图像使用CoreData。 这里是我作为NSInvocationOperation运行的代码:

 -(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 && [data length] > 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]; } 

所有CoreData相关的东西都在Main-Thread中完成,所以不应该有任何CoreDatamultithreading问题。 但是,如果我坚持使用这些图像,乐器会在上述位置显示增加的内存分配。

编辑二:

CoreData相关代码:

 -(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]; } 

从CoreDataHelper(self.managedObjectContext正在挑选当前线程中可用的NSManagedObjectContext):

 -(NSManagedObject *) createObject:(NSString *) entityName { return [NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:self.managedObjectContext]; } 

我们有类似的问题。 在通过http获取大量图片的同时,内存分配也出现了巨大的增长和锯齿模式。 我们可以看到系统清理了,或多或less,但是慢慢地,而不是可预测的。 与此同时,下载stream入,堆积在内存上。 内存分配将高达200M左右,然后我们会死。

问题是一个NSURLCache问题。 你说你试过[[NSURLCache sharedURLCache] removeAllCachedResponses]。 我们也尝试过,但后来尝试了一些不同的东西。

我们的下载是以N个图像/电影的组合来完成的,其中N通常是50到500.重要的是我们把所有的N作为一个primefaces操作。

在我们开始我们的http下载组之前,我们这样做了:

 NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:0]; [NSURLCache setSharedURLCache:sharedCache]; 

然后我们通过一个同步调用在http上通过http获得每个图像。 我们在NSOperation中做这个组下载,所以我们不阻止UI。

 NSData *movieReferenceData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; 

最后,在每个单独的图像下载之后,在我们完成了我们的NSData对象的图像之后,我们调用:

 [sharedCache removeAllCachedResponses]; 

我们的内存分配高峰行为下降到一个非常舒适的几兆字节,并停止增长。

在这种情况下,你正在看到你应该看到什么。 -[NSMutableData appendData:]增加了内部缓冲区的大小来保存新的数据。 由于NSMutableData始终位于内存中,因此会相应增加内存使用量。 你在期待什么?

如果这些映像的最终目标位于磁盘上,请尝试使用NSOutputStream而不是NSMutableData 。 如果您希望显示图像,则可以在完成后创build指向该文件的UIImage