美文网首页iOS那点事儿iOS自我学习库
iOS 批量下载多张图片,保持原始顺序

iOS 批量下载多张图片,保持原始顺序

作者: zhangyin | 来源:发表于2018-02-28 15:17 被阅读1265次

    经常会遇到这样的应用场景,例如在调用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];
                    }];
    

    相关文章

      网友评论

      • Buger123:最多下载五张啊,怎么解决
        zhangyin:调用方法前限制一下呗~
      • Buger123:顺序下载图片保存在哪里
        Buger123:@zhangyin 嗯,明白了,我是把图片保存到相册中去,已经解决了
        zhangyin:放在内存当中,可以直接使用哦,就是下面这段:
        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];
        }
        }
      • PGOne爱吃饺子:楼主,标题下载多张图片保持原始顺序是什么意思
        zhangyin:@PGOne爱吃饺子 sd是异步下载的,下载完成后,在本地拼装成顺序的。 代码比较简单粗暴。
        使用循环变量 i 作为 一个dictionary的key,用来保存每个异步回来的结果;
        最后使用循环把图片按照顺序循环出来;

        另外,i 被包含进block中, 当sd的异步返回时,i的值是安全的,仍然是它刚被包含进去时值;
        PGOne爱吃饺子:那你写的这个方法应该不是按照顺序下载的吧,SDWebImageDownloader这个类里面下载图片的时候就是异步的
        zhangyin:我的本意是:如果打算批量下载图片A,B,C,那么批量下载完成后,返回的图片顺序还是A、B、C这样的顺序,保持与下载前的顺序相同。
        由于网络及各种灵异的原因,当多个线程同时开启下载,返回的图片顺序可能会乱序,例如C、B、A这样;(假设C线程中的任务跑的最快)
      • llq_31da:有没有碰到,多张图片,有时候其中某张不下载的情况???
        llq_31da:@zhangyin 找到原因了,是后台返回的图片URL不规范,带有其他字符:sweat:
        zhangyin:因为我觉得,无论做多么努力的尝试,总是会遇见各种网络问题,这是无法克服的障碍,与其在重试的方案上花费很多精力去优化,不如简单处理。相信用户是可以理解和接受的。
        zhangyin:有的,这种情况非常常见,我现在的处理方法就是简单粗暴的丢弃它。

      本文标题:iOS 批量下载多张图片,保持原始顺序

      本文链接:https://www.haomeiwen.com/subject/zizbxftx.html