最近真的真的太太太忙了,都是抽空写的,各种事情,html,iOS客户端升级,炸了
上一篇我们基本上看完了SDWebImage
整个工作流程,下面我们具体看一下缓存下载图片中涉及到的相关的类
SDWebImageDownloader
SDWebImageManager
实现下载依赖于下载器:SDWebImageDownloader
,下载器负责管理下载任务,而执行下载任务是由SDWebImageDownloaderOperation
操作完成
SDWebImageManager
实现下载 就是调用下面这个方法:
1 2 3 4 |
- (id)downloadImageWithURL:(NSURL *)url options:(SDWebImageDownloaderOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageDownloaderCompletedBlock)completedBlock |
我们还是先来看看SDWebImageDownloader
里面都写了些什么
SDWebImageDownloader.h
1 2 3 4 |
typedef NS_OPTIONS(NSUInteger, SDWebImageDownloaderOptions) { //这个属于默认的使用模式了,前往下载,返回进度block信息,完成时调用completedBlock SDWebImageDownloaderLowPriority = 1 |
这些选项主要涉及到下载的优先级,缓存,后台任务执行,cookie处理以及证书认证几个方面,在创建下载操作的时候可以使用组合的选项来完成一些特殊的需求
定义里两个常量,后面通知的时候用的,这里的常量是全局常量
全局常量:不管你定义在任何文件夹,外部都能访问
1 |
const NSString *myName = @"杨千嬅染了红头发"; |
局部常量:用static修饰后,不能提供外界访问(只能在赋值的.m文件使用,外界不可访问)
1 |
static const NSString *myName= @"杨千嬅染了红头发"; |
1 2 3 |
//官方也更推荐这样定义常量 而不是用#define extern NSString *const SDWebImageDownloadStartNotification; extern NSString *const SDWebImageDownloadStopNotification; |
定义了三个block
- 第一个返回已经接收的图片数据的大小,未接收的图片数据的大小,
- (void)sd_setImageWithPreviousCachedImageWithURL: placeholderImage: options: progress:completed:
这个方法里面就有用到,因为图片的下载是需要时间的,所以这个block回调不止回调一次,会一直持续到图片完全下载或者下载失败才会停止回调 - 第二个block回调 下载完成的图片 , 图片的数据 , 如果有error返回error ,以及下载是否完成的BOOl值
- 第三个是header过滤:设置一个过滤器,为下载图片的HTTP request选取header.最终使用的headers是经过这个block过滤时候的返回值
1 2 3 4 5 |
typedef void(^SDWebImageDownloaderProgressBlock)(NSInteger receivedSize, NSInteger expectedSize); typedef void(^SDWebImageDownloaderCompletedBlock)(UIImage *image, NSData *data, NSError *error, BOOL finished); typedef NSDictionary *(^SDWebImageDownloaderHeadersFilterBlock)(NSURL *url, NSDictionary *headers); |
定义的属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
/** * 解压已经下载缓存起来的图片可以提高性能,但是会消耗大量的内存 * 默认为YES显示比较高质量的图片,如果你遇到因内存消耗过多而造成崩溃的话可以设置为NO, */ @property (assign, nonatomic) BOOL shouldDecompressImages; //下载队列最大的并发数,意思是队列中最多同时运行几条线程(全局搜索了一下,默认值是3) @property (assign, nonatomic) NSInteger maxConcurrentDownloads; /** * 当前在下载队列的操作总数,只读(这是一个瞬间值,因为只要一个操作下载完成就会移除下载队列) */ @property (readonly, nonatomic) NSUInteger currentDownloadCount; /** * 下载操作的超时时间,默认是15s */ @property (assign, nonatomic) NSTimeInterval downloadTimeout; /** * 枚举类型,代表着操作下载的顺序 */ @property (assign, nonatomic) SDWebImageDownloaderExecutionOrder executionOrder; //SDWebImageDownloaderExecutionOrder 的定义 typedef NS_ENUM(NSInteger, SDWebImageDownloaderExecutionOrder) { /** * 默认值,所有的下载操作以队列类型(先进先出)执行 */ SDWebImageDownloaderFIFOExecutionOrder, /** * 所有的下载操作以栈类型(后进后出)执行 */ SDWebImageDownloaderLIFOExecutionOrder }; /** * SDWeImageDownloder是一个单例,这是初始化方法 */ + (SDWebImageDownloader *)sharedDownloader; /** * 为request操作设置默认的URL凭据,具体实施为:在将操作添加到队列之前,将操作的credential属性值设置为urlCredential */ @property (strong, nonatomic) NSURLCredential *urlCredential; /** * Set username */ @property (strong, nonatomic) NSString *username; /** * Set password */**局部常量** @property (strong, nonatomic) NSString *password; /** * 设置一个过滤器,为下载图片的HTTP request选取header.意味着最终使用的headers是经过这个block过滤之后的返回值。 */ @property (nonatomic, copy) SDWebImageDownloaderHeadersFilterBlock headersFilter; |
看完这些属性后我们在来看SDWebImageDownloader里面的两个核心方法,其他的方法会捎带说一下
第一个就是一开始我们说的,SDWebImageManager会调用的方法
1 2 3 4 5 6 7 8 9 10 11 12 |
- (id )downloadImageWithURL:(NSURL *)url options:(SDWebImageDownloaderOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageDownloaderCompletedBlock)completedBlock { __block SDWebImageDownloaderOperation *operation; __weak __typeof(self)wself = self; [self addProgressCallback:progressBlock completedBlock:completedBlock forURL:url createCallback:^{ //这里面都是创建下载的回调 }]; } |
先来看看-addProgressCallback:completedBlock:forURL:createCallback:
里面都做了些什么
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
- (void)addProgressCallback:(SDWebImageDownloaderProgressBlock)progressBlock completedBlock:(SDWebImageDownloaderCompletedBlock)completedBlock forURL:(NSURL *)url createCallback:(SDWebImageNoParamsBlock)createCallback { // The URL will be used as the key to the callbacks dictionary so it cannot be nil. If it is nil immediately call the completed block with no image or data. //如果图片的url是空的就直接返回 if (url == nil) { if (completedBlock != nil) { completedBlock(nil, nil, nil, NO); } return; } dispatch_barrier_sync(self.barrierQueue, ^{ BOOL first = NO; if (!self.URLCallbacks[url]) { self.URLCallbacks[url] = [NSMutableArray new]; first = YES; } // Handle single download of simultaneous download request for the same URL NSMutableArray *callbacksForURL |