我有一个我正在编写的应用程序需要下载大量图像,可能是10,000。现在,在内存不足和应用程序崩溃之前,我可以达到大约3000,这取决于图像文件的大小。我正在后台线程下载它们并向用户显示进度。
我写了一个帮助类,我正在访问这样做,并想知道这是我的问题所在,我只是在泄漏记忆。
这是下载图像的循环 - 这是在后台线程上运行的,这都在NSAutoReleasePool中:
for (int j=0; j < [items count]; j++)
{
ImagesHelper *helper = [[ImagesHelper alloc]init];
[helper downloadImages: [[items objectAtIndex:j] valueForKey:@"ItemSKU"] withManufacturer: [[manufacturers objectAtIndex:i] ManufacturerID]];
[helper release];
if (j%50==0) { //this notifies the user of progress
statusMessage = [NSString stringWithFormat:@"Downloading images: %@.jpg (%d of %d)", [[items objectAtIndex:j] valueForKey:@"ItemSKU"],j+1, [items count]];
[self performSelectorOnMainThread:@selector(setStatus) withObject:nil waitUntilDone:YES];
}
}
这是我的助手类:
-(void) downloadImages:(NSString *)ItemSKU withManufacturer: (NSString *) aManufacturerID{
NSData *imageData = nil;
NSData *imageDataLarge=nil;
NSString *fileName = [NSString stringWithFormat:@"%@_tn.jpg", [ItemSKU stringByReplacingOccurrencesOfString:@" " withString:@""]];
NSString *fileNameLarge = [NSString stringWithFormat:@"%@_lg.jpg", [ItemSKU stringByReplacingOccurrencesOfString:@" " withString:@""]];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
NSString *savePath = [documentsPath stringByAppendingPathComponent:fileName];
NSString *savePathLarge = [documentsPath stringByAppendingPathComponent:fileNameLarge];
/* go get the image */
NSString *URL = [NSString stringWithFormat:kProductImagesURL,aManufacturerID, fileName];
NSString *URLLarge = [NSString stringWithFormat:kProductImagesURL,aManufacturerID, fileNameLarge];
NSLog(@"Going to get the file: %@",URL);
imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:URL]];
if (imageData!=nil) {
[imageData writeToFile:savePath atomically:YES];
}
imageDataLarge = [NSData dataWithContentsOfURL:[NSURL URLWithString:URLLarge]];
if (imageDataLarge!=nil) {
[imageDataLarge writeToFile:savePathLarge atomically:YES];
}
imageData = nil;
imageDataLarge=nil;
}
仍然试图了解其中一些概念。
答案 0 :(得分:2)
您是否尝试过构建和分析?这可能有所帮助。也可以玩乐器。最后,我建议使用NSOperationQueue。这样你就可以并行完成它们。此外,在控制权返回主线程之前,您的AutoReleasePool可能不会自动释放任何内容。
答案 1 :(得分:1)
您正在使用的每个工厂方法(stringWith *,stringBy *,URLwith *,dataWith *等)都返回一个自动释放的对象,其池在循环结束之前不会为空。对内容进行alloc init
,然后在完成后再release
。你应该看到更好的结果。
答案 2 :(得分:1)
戴夫说的正确......使用NSInvocationOperation
。这将解决问题,而不是分裂代码块。这是我使用的样本
NSOperationQueue *downloadQueue = [NSOperationQueue new];
for (Product *cProduct in productsMasterArray)
{
NSInvocationOperation *downloadOperation = [[NSInvocationOperation alloc]
initWithTarget:self selector:@selector(downloadImages:)
object:cProduct.ITEM_CODE];
[downloadQueue addOperation:downloadOperation];
[downloadOperation release];
}