在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
。