在我的应用中,我需要下载约6,000
张图片。我意识到这很多,但需要它。
目前我正在使用以下内容:
NSArray *photos = @[hugeAmountOfPhotoObjects];
for (ZSSPhoto *photo in photos) {
[self downloadImageWithURL:photo.mobileURL progress:^(double progress) {
} completion:^(UIImage *image) {
// Save the image
} failure:^(NSError *error) {
}];
}
...
- (void)downloadImageWithURL:(NSURL *)url progress:(void (^)(double progress))progress completion:(void (^)(UIImage *image))completion failure:(void (^)(NSError *error))failure {
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setTimeoutInterval:600];
self.operationQueue.maxConcurrentOperationCount = NSOperationQueueDefaultMaxConcurrentOperationCount;
AFHTTPRequestOperation *requestOperation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
requestOperation.responseSerializer = [AFImageResponseSerializer serializer];
[requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
completion(responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[self processOperation:operation error:error failure:failure];
}];
[requestOperation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
double percentDone = (double)totalBytesRead / (double)totalBytesExpectedToRead;
progress(percentDone);
}];
[self.operationQueue addOperation:requestOperation];
}
这里的问题是使用此方法下载需要花费很长时间,并且由于内存使用率过高,我的一些用户报告崩溃。
有没有更好的方法可以用来下载如此大量的图像文件?
答案 0 :(得分:0)
你可以稍微递归地试试
NSMutableArray *undownloaded;
- (void) startDownload {
undownloaded = [photos mutableCopy]; //get a list of the undownloaded images
for(int i = 0; i < 3;i++) //download 3 at a time
[self downloadImage];
}
- (void) downloadImage {
if(undownloaded.count > 0){
ZSSPhoto *photo = undownloaded.firstObject;
[undownloaded removeObjectAtIndex:0];
[self downloadImageWithURL:photo.mobileURL progress:^(double progress) {
} completion:^(UIImage *image) {
// Save the image
[self downloadImage];
} failure:^(NSError *error) {
[self downloadImage];
//[undownloaded addObject:photo]; //insert photo back into the array maybe to retry? warning, could cause infinite loop without some extra logic, maybe the object can keep a fail count itself
}];
}
}
警告:未经测试的代码,可能需要一些调整
答案 1 :(得分:0)
速度问题可以解决(速度会增加,但可能仍然很慢)使用多线程,同时下载所有图像而不是每次下载一次。但是,内存问题有点复杂。
ARC将在所有图像完成后释放所有图像,但在此之前,您将在设备内存中拥有6,000张图像。您可以优化图像,降低分辨率或按步骤下载它们,例如Google Images(您下载的图像最初会显示,然后当用户向下滚动时,您将图像加载到新的可见区域;下载图像只有在他们需要的时候)。
考虑到您正在下载足够的图像以解决内存问题,如果您下载了所有这些内容,则可能会占用用户设备的大量空间,以及“步骤”。解决方案也可以解决这个问题。
现在,让我们假设您必须同时下载所有这些并且空间不是问题:我想如果您将downloadImageWithURL:progress:
方法放在并发队列中,那么图像只是在保存之后才能从记忆中解脱出来(这只是一个假设)。将其添加到您的代码中:
dispatch_queue_t defaultPriorityQueueWithName(const char* name)
{
dispatch_queue_t dispatchQueue = dispatch_queue_create(name, DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t priorityQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_set_target_queue(dispatchQueue, priorityQueue);
return dispatchQueue;
}
将代码更改为:
dispatch_queue_t threadItemLoadImage = defaultPriorityQueueWithName("DownloadingImages");
NSArray *photos = @[hugeAmountOfPhotoObjects];
for (ZSSPhoto *photo in photos)
{
dispatch_async(threadItemLoadImage, ^
{
[self downloadImageWithURL:photo.mobileURL progress:^(double progress) {
} completion:^(UIImage *image) {
// Save the image
} failure:^(NSError *error) {
}];
});
}
如果更新了某些视图,则需要删除setDownloadProgressBlock:
,因为它们会同时下载。另外,警告:totalBytesExpectedToRead
并不总是会在第一次被正确检索,包含0,这可能会使您的应用程序崩溃,在某些罕见情况下除以零。在将来的情况下,当您需要使用setDownloadProgressBlock:
时,请在进行此除法之前检查totalBytesExpectedToRead
值。