图片下载器


    写了个图片下载器,当然没法跟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

#import

@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的编辑器可以编辑代码,不会这么乱,不会用,下次学学。

你可能感兴趣的:(图片下载器)