我正在实现一个需要通过HTTP获取大量图像的iOS应用程序。我已经尝试了几种方法但独立完成了我的工作,Instuments显示不断增加的内存分配,并且当我在设备上运行它时,应用程序迟早会崩溃。仪器没有泄漏。
到目前为止,我尝试了以下方法:
Instrumetns中的调用树显示在处理HTTP响应时消耗了内存。在异步NSURLConnection的情况下,这是在
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[receivedData appendData:data];
}
在同步NSURLConnection的情况下,Instruments显示了不断增长的CFData(商店)条目。 ASIHTTPRequest的问题似乎与类似代码位置中的异步NSURLConnection相同。 [NSData dataWithContentsOfURL:url]方法在该语句中显示了越来越多的总内存分配。
当请求在一个单独的线程中完成时,我正在使用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中完成,所以不应该有任何CoreData多线程问题。但是,如果我保留图像,仪器会在上述位置显示不断增加的内存分配。
编辑II:
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];
}
答案 0 :(得分:9)
我们遇到了类似的问题。在通过http获取大量图像的同时,内存分配中出现了巨大的增长和锯齿模式。我们会看到系统或多或少地清理,但是很慢,而且不可预测。与此同时,下载量正在流入,堆积在内存上的任何内容上。内存分配将达到200M左右,然后我们就会死亡。
问题是NSURLCache问题。你声明你试过[[NSURLCache sharedURLCache] removeAllCachedResponses]。我们也试过了,但后来尝试了一些不同的东西。
我们的下载是在 N 图像/电影的组中完成的,其中 N 通常为50到500.重要的是我们得到所有 N < / em>作为原子操作。
在开始我们的http下载组之前,我们这样做了:
NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:0];
[NSURLCache setSharedURLCache:sharedCache];
然后我们通过同步调用通过http获取 N 中的每个图像。我们在NSOperation中进行此组下载,因此我们不会阻止UI。
NSData *movieReferenceData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
最后,在每个单独的图像下载之后,以及在我们完成该图像的NSData对象之后,我们称之为:
[sharedCache removeAllCachedResponses];
我们的内存分配峰值行为下降到非常舒适的几兆字节,并且停止增长。
答案 1 :(得分:0)
在这种情况下,你会看到你应该看到的确切内容。 -[NSMutableData appendData:]
增加其内部缓冲区的大小以容纳新数据。由于NSMutableData
始终位于内存中,因此会导致内存使用量相应增加。你有什么期待?
如果这些图片的最终目的地位于磁盘上,请尝试使用NSOutputStream
代替NSMutableData
。如果您想要显示图像,则可以在完成后创建指向该文件的UIImage
。