我正在实现一个需要通过 HTTP 获取大量图像的 iOS 应用程序。我尝试了几种方法,但独立于我所做的事情,Instuments 显示内存分配不断增加,当我在设备上运行它时,应用程序迟早会崩溃。仪器显示没有泄漏。
到目前为止,我已经尝试了以下方法:
- 使用 NSOperation 中的同步 NSURLConnection 获取图像
- 使用 NSOperation 中的异步 NSURLConnection 获取图像
- 在主线程中使用 [NSData dataWithContentsOfURL:url] 获取图像
- 使用 NSOperation 中的同步 ASIHTTPRequest 获取图像
- 使用异步 ASIHTTPRequest 获取图像并将其添加到 NSOperationQueue
- 使用异步 ASIHTTPRequest 并使用 completionBlock 获取图像
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 相关的东西都在这里的主线程中完成,所以不应该有任何 CoreData 多线程问题。但是,如果我保留图像,仪器会在上述位置显示不断增加的内存分配。
编辑二:
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];
}