图片下载器


    写了个图片下载器,当然没法跟SDWebImageDownloader比,SDWebImageDownloader考虑到了各个方方面面,但是大致的下载器的框架时出来了,更最重要的是这种编程的思想,说到这,想起了高中化学老师的一句话:有思路就有出路,个人觉得编程也是如此,编程的思想更重要!!!

JGWebImgOperation.h

#import

#import "JGWebImgDownloader.h"

#import@interface JGWebImgOperation : NSOperation

-(id)initWithUrlStr:(NSString*)urlStr

              Progress:(JGWebImgDownloaderProgress)progressBlock

              Finished:(JGWebImgDownloaderFinished)finishedBlock

              Cancel:(JGWebImgDownloaderCancel)cancelBlock;

@end


JGWebImgOperation.m

#import "JGWebImgOperation.h"

@interface JGWebImgOperation ()

@property(nonatomic,copy)NSString *urlStr;

@property(nonatomic,copy)JGWebImgDownloaderProgress progressBlock;

@property(nonatomic,copy)JGWebImgDownloaderFinished finishedBlock;

@property(nonatomic,copy)JGWebImgDownloaderCancel cancelBlock;

@property(nonatomic,strong)NSMutableData *imgData;

@property(nonatomic,assign)NSInteger expectSize;

@property(nonatomic,assign)NSInteger downTimeout;

@property(nonatomic,assign)BOOL isFinished;

@end

/**

       初始化一个下载操作

       @param urlStr 图片的路径

       @param progressBlock 图片下载过程中进度回调

       @param finishedBlock  图片下载完(包括下载失败)回调

       @ cancelBlock 取消操作的回调

**/

-(id)initWithUrlStr:(NSString*)urlStr

              Progress:(JGWebImgDownloaderProgress)progressBlock

              Finished:(JGWebImgDownloaderFinished)finishedBlock

              Cancel:(JGWebImgDownloaderCancel)cancelBlock

{

             if (self = [super init]) {

                   _urlStr = urlStr;          

                   _progressBlock = [progressBlock copy];

                   _finishedBlock = [finishedBlock copy];

                   _cancelBlock  = [cancelBlock copy];

                 _isFinished = NO;

          }

          return self; 

}

/**

       重写NSOperation的main方法, 具体任务都封装在此方法中

**/

-(void)main

{

           NSURL *url = [NSURL URLWithString:_urlStr];

           NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:_downTimeout];

          //NSURLConnection xcode7.1好几个方法都被废弃了,不过尽管废弃了,还可以用

            NSURLConnection *connect = [[NSURLConnection alloc] initWithRequest:request delegate:self];

            [connect start];

            //保存图片下载完或者失败后才退出此函数

            while (!_isFinished) {

                   [[NSRunLoop currentRunLoop] run];

            }

            NSLog(@"finished");

}

-(NSMutableData*)imgData

{

          if (!_imgData) {

                   _imgData = [NSMutableData data];

           }

           return _imgData;

}

#pragma mark ------NSURLConnectionDataDelegate-------


- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error

{

           dispatch_async(dispatch_get_main_queue(), ^{

                    if (_finishedBlock) {

                               _finishedBlock(nil,nil,nil,YES);

                    }

         });

         _isFinished = YES;

         NSLog(@"failed down with error %@ ",error);

}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response

{

            _expectSize = response.expectedContentLength;

            NSLog(@"respoinse : %@",response);

}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data

{

           //追加数据

           [self.imgData appendData:data];

            if (_progressBlock) { 

                   _progressBlock(self.imgData.length,_expectSize);

            }

}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection

{

             UIImage *image = [[UIImage alloc] initWithData:self.imgData];

             //成功回调可能更新UI操作,故而使用主队列,保证UI操作在主线程中

             dispatch_async(dispatch_get_main_queue(), ^{

                   if (_finishedBlock) {

                                 _finishedBlock(image,self.imgData,nil,YES);

                    } 

          });

          _isFinished = YES;

}


JGWebImgDownloader.h

#import<Foundation/Foundation.h>

#import<UIKit/UIKit.h>

@class JGWebImgOperation;

typedef void(^JGWebImgDownloaderProgress)(NSInteger recesiveSize,NSInteger expectSize);

typedef void(^JGWebImgDownloaderFinished)(UIImage *image,NSData *data,NSError *error,BOOL isFinish);

typedef void (^JGWebImgDownloaderCancel)();

@interface JGWebImgDownloader : NSObject

/**

       获取下载器全局单列

**/

+(id)shareJGWebIMgDownLoader;

/**

        下载图片

       @param urlStr 图片路径

       @param  progressBlock 进度回调

       @param finishedBlock   下载图片后回调

**/

-(JGWebImgOperation*)downImgWithUrlStr:(NSString*)urlStr

                                                     Progree:            (JGWebImgDownloaderProgress)progressBlock

                                                    Finished:(JGWebImgDownloaderFinished)finishedBlock;

@end

JGWebImgDownloader.m

#define finishedCallbackKey  @"finishedCallbackKey"

#define progressCallbackKey  @"progressCallbackKey"

#import "JGWebImgDownloader.h"

#import "JGWebImgOperation.h"

@interface JGWebImgDownloader()

@property(nonatomic,strong)NSMutableArray *operationArr;

@property(nonatomic,strong)NSMutableDictionary *callbackDict;

//下载队列了

@property(nonatomic,strong)NSOperationQueue *downOperationQueue;

@property(nonatomic,strong)dispatch_queue_t  barrierQueue;

@end

static JGWebImgDownloader *shareDownloader = nil;

/**

        单列

**/

+(id)shareJGWebIMgDownLoader

{

            static dispatch_once_t onceToken;

            dispatch_once(&onceToken, ^{

                      shareDownloader = [[JGWebImgDownloader alloc] init];

            });

            return shareDownloader;

}

 /**

      简单的初始化

**/

-(id)init

{

            if (self = [super init])

             {

                      [self createDownLoadQueue];

                       _barrierQueue = dispatch_queue_create("com.text.jg",  DISPATCH_QUEUE_CONCURRENT);

             }

             return self;

}

-(void)dealloc

{

            [self.downOperationQueue cancelAllOperations];

}

-(void)createDownLoadQueue

{

             _downOperationQueue = [[NSOperationQueue alloc]init];

            _downOperationQueue.maxConcurrentOperationCount = 3;

}

/**

           下载图片

           @param urlStr 图片路径

           @param  progressBlock 进度回调 

           @param finishedBlock  下载图片后回调

**/

-(JGWebImgOperation*)downImgWithUrlStr:(NSString*)urlStr

                                     Progree:(JGWebImgDownloaderProgress)progressBlock

                                     Finished:(JGWebImgDownloaderFinished)finishedBlock

{

                 __block JGWebImgOperation *operation = nil;

                 __weak typeof(self) sf = self;

                [self addCallbackFinished:finishedBlock

                                          Progress:progressBlock 

                                           ForurlStr:urlStr

                                           CreateOperation:^{

                                     operation = [[JGWebImgOperation alloc]        initWithUrlStr:urlStr Progress:^(NSInteger recesiveSize, NSInteger expectSize) {

                                    __block NSArray *array = nil;

                                   dispatch_barrier_sync(_barrierQueue, ^{

                                          array = self.callbackDict[urlStr];

                                  });

                                  for (NSDictionary *dict  in  array) {

                                            JGWebImgDownloaderProgress progress = dict[progressCallbackKey];

                                            if (progress) {

                                                         progress(recesiveSize,expectSize);

                                             }

                                  }

                         } Finished:^(UIImage *image, NSData *data, NSError *error, BOOL  isFinish)   {

                      __block NSArray *array = nil;

                     dispatch_barrier_sync(_barrierQueue, ^{

                     array = self.callbackDict[urlStr];

                    if (isFinish) {

                              [self.callbackDict removeObjectForKey:urlStr];

                     }

                    });

                    for (NSDictionary *dict  in  array) {

                                 JGWebImgDownloaderFinished finished = dict[finishedCallbackKey];

                                if (finished) {

                                    finished(image,data,error,isFinish);

                             }

                   }

          } Cancel:^{

                     dispatch_barrier_async(_barrierQueue, ^{

                    [self.callbackDict removeObjectForKey:urlStr];

         });

 }];

      [sf.downOperationQueue addOperation:operation];

 }];

      return operation;

}

/**

     保存回调block,并判断是非在下载,如果没有下载,创建下载任务

**/

-(void)addCallbackFinished:(JGWebImgDownloaderFinished)finishedBlock

             Progress:(JGWebImgDownloaderProgress)progressBlock

              ForurlStr:(NSString*)urlStr

              CreateOperation:(void (^)()) createOperaion

{

             if (!urlStr || [urlStr isEqualToString:@""]) {

                      if (finishedBlock) {

                                 finishedBlock(nil,nil,nil,NO);

                                  return;

                     }

             }

            //需要判断是否在下载中

            dispatch_barrier_sync(self.barrierQueue, ^{

                     BOOL isFirst = NO;

                     NSArray *callbacks = self.callbackDict[urlStr];

                    if (!callbacks) {

                            self.callbackDict[urlStr] = [NSMutableArray array];

                            isFirst = YES;

                   }

                 if (isFirst) {

                     //self.callbackDict为临界资源,避免多个线程同时操作,故而使用了                  dispatch_barrier_async

                   NSMutableArray *array = self.callbackDict[urlStr];

                   NSMutableDictionary *callbackDt = [NSMutableDictionary dictionary];

                   if (finishedBlock) {

                            callbackDt[finishedCallbackKey] = [finishedBlock copy];

                  }

                if (progressBlock) {

                       callbackDt[progressCallbackKey] = [progressBlock copy];

                }

               [array addObject:callbackDt];

              if (createOperaion)

             {

                        createOperaion();

             }

        }

    });

}


-(NSMutableArray*)operationArr

{

         if (!_operationArr) {

                 _operationArr = [NSMutableArray array]; 

         }

        return _operationArr;

}

-(NSMutableDictionary*)callbackDict

{

         if (!_callbackDict) {

               _callbackDict = [NSMutableDictionary dictionary];

         }

        return _callbackDict;

}

使用

JGWebImgDownloader *imageDownloader = [JGWebImgDownloader shareJGWebIMgDownLoader];

[imageDownloader    downImgWithUrlStr:@"http://www.blisscake.cn/Upload/Product/Show/Source/ps_1507201119031647109.jpg" Progree:^(NSInteger recesiveSize, NSInteger expectSize) {

               NSLog(@"download rate : %.5f", recesiveSize/(double)expectSize);

} Finished:^(UIImage *image, NSData *data, NSError *error, BOOL isFinish) {

          _imgView.image = image;

}];

  代码有点乱啊 ,有个makedown的编辑器可以编辑代码,不会这么乱,不会用,下次学学。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,219评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,363评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,933评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,020评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,400评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,640评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,896评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,597评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,327评论 1 244
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,581评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,072评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,399评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,054评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,849评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,672评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,585评论 2 270

推荐阅读更多精彩内容