经常会遇到这样的应用场景,例如在调用iOS系统分享功能前(UIActivityViewController),需要将所有的图片事先准备好,但是图片都在网络上.
这时,就需要先将图片都下载好后再进行调用.
可能是这个功能的实现太简单了,所以像SDWebImage,AFNetwork等都没有提供可以直接调用的API方法.
所以只好花了2秒钟自己写了一个方法;
#import "ImagesDownloadManager.h"
#import "SDWebImageDownloader.h"
@implementation ImagesDownloadManager
/**
批量下载图片
保持顺序;
全部下载完成后才进行回调;
回调结果中,下载正确和失败的状态保持与原先一致的顺序;
@return resultArray 中包含两类对象:UIImage , NSError
*/
+ (void)downloadImages:(NSArray<NSString *> *)imgsArray completion:(void(^)(NSArray *resultArray))completionBlock {
SDWebImageDownloader *manager = [SDWebImageDownloader sharedDownloader];
manager.downloadTimeout = 20;
__block NSMutableDictionary *resultDict = [NSMutableDictionary new];
for(int i=0;i<imgsArray.count;i++) {
NSString *imgUrl = [imgsArray objectAtIndex:i];
[manager downloadImageWithURL:[NSURL URLWithString:imgUrl]
options:SDWebImageDownloaderUseNSURLCache|SDWebImageDownloaderScaleDownLargeImages
progress:^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) {
} completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, BOOL finished) {
if(finished){
if(error){
//在对应的位置放一个error对象
[resultDict setObject:error forKey:@(i)];
}else{
[resultDict setObject:image forKey:@(i)];
}
if(resultDict.count == imgsArray.count) {
//全部下载完成
NSArray *resultArray = [ImagesDownloadManager createDownloadResultArray:resultDict count:imgsArray.count];
if(completionBlock){
completionBlock(resultArray);
}
}
}
}];
}
}
+ (NSArray *)createDownloadResultArray:(NSDictionary *)dict count:(NSInteger)count {
NSMutableArray *resultArray = [NSMutableArray new];
for(int i=0;i<count;i++) {
NSObject *obj = [dict objectForKey:@(i)];
[resultArray addObject:obj];
}
return resultArray;
}
@end
调用方法:
//下载图片
[ImagesDownloadManager downloadImages:imgs completion:^(NSArray *resultArray) {
NSMutableArray *items = [NSMutableArray new];
for(int i=0;i<resultArray.count;i++) {
NSObject *obj = [resultArray objectAtIndex:i];
if([obj isKindOfClass:[UIImage class]]) {
//只取UIImage对象,其他类型忽略之
[items addObject:obj];
}
}
//调用系统自带的分享功能,把选中的图片们分享出去
UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:items applicationActivities:nil];
[self presentViewController:activityVC animated:YES completion:nil];
}];
网友评论
NSMutableArray *items = [NSMutableArray new];
for(int i=0;i<resultArray.count;i++) {
NSObject *obj = [resultArray objectAtIndex:i];
if([obj isKindOfClass:[UIImage class]]) {
//只取UIImage对象,其他类型忽略之
[items addObject:obj];
}
}
使用循环变量 i 作为 一个dictionary的key,用来保存每个异步回来的结果;
最后使用循环把图片按照顺序循环出来;
另外,i 被包含进block中, 当sd的异步返回时,i的值是安全的,仍然是它刚被包含进去时值;
由于网络及各种灵异的原因,当多个线程同时开启下载,返回的图片顺序可能会乱序,例如C、B、A这样;(假设C线程中的任务跑的最快)