SDWebImage源码分析
每次读优秀的代码都是一次深刻的学习,每一次模仿,都是创造的开始!
——QQ 316045346 欢迎交流
SDWebImage是iOS开发中非常流行的一个网络图片加载库,如果你观察其源码,会发现其中的文件非常多,虽然文件数很多,但是作者的代码结构和条理却是非清晰。SDWebImage的代码结构基本可以分为3块:应用层类别、核心功能类、工具类与类别。其中我们最常使用的是应用层的类别。例如UIImageView的图片加载,UIButton的图片加载等。
一、帮助类与类别的解析
1.NSData+ImageContentType
这个类别是一个图片数据的格式帮助类,使用它可以方便的获取图片数据的图片格式,其中枚举了常用的图片格式如下:
1 2 3 4 5 6 7 8 9
| typedef NS_ENUM(NSInteger, SDImageFormat) { SDImageFormatUndefined = -1, SDImageFormatJPEG = 0, SDImageFormatPNG, SDImageFormatGIF, SDImageFormatTIFF, SDImageFormatWebP, SDImageFormatHEIC };
|
其原理是根据图片数据的第1个字节码进行分析,不同格式的图像数据在开头都会有一部分的用来表明图像信息的数据块,通过它可以获取图片的具体格式。这个类别中只提供了两个方法:
1 2 3 4
| + (SDImageFormat)sd_imageFormatForImageData:(nullable NSData *)data;
+ (nonnull CFStringRef)sd_UTTypeFromSDImageFormat:(SDImageFormat)format;
|
2、SDWebImageFrame
这个类是SDWebImage中封装的图像帧类,主要用来创建动画图像。
1 2 3 4 5 6
| @property (nonatomic, strong, readonly, nonnull) UIImage *image;
@property (nonatomic, readonly, assign) NSTimeInterval duration;
+ (instancetype _Nonnull)frameWithImage:(UIImage * _Nonnull)image duration:(NSTimeInterval)duration;
|
3.UIImage的编码与解码
SDWebImageCoder中定义了一个协议,其中约定了方法来对图像数据进行解码与编码,实现这个协议的主要有SDWebImageIOCoder和SDWebImageGIFCoder。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| - (BOOL)canDecodeFromData:(nullable NSData *)data;
- (nullable UIImage *)decodedImageWithData:(nullable NSData *)data;
- (nullable UIImage *)decompressedImageWithImage:(nullable UIImage *)image data:(NSData * _Nullable * _Nonnull)data options:(nullable NSDictionary<NSString*, NSObject*>*)optionsDict;
- (BOOL)canEncodeToFormat:(SDImageFormat)format;
- (nullable NSData *)encodedDataWithImage:(nullable UIImage *)image format:(SDImageFormat)format;
- (BOOL)canIncrementallyDecodeFromData:(nullable NSData *)data;
- (nullable UIImage *)incrementallyDecodedImageWithData:(nullable NSData *)data finished:(BOOL)finished;
|
4.图像数据预加载
SDWebImagePrefetcher类提供了图像数据的预加载功能,在进行用户体验优化,需要预加载某些常态图像时,可以用使用这个类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @interface SDWebImagePrefetcher : NSObject
@property (strong, nonatomic, readonly, nonnull) SDWebImageManager *manager;
@property (nonatomic, assign) NSUInteger maxConcurrentDownloads;
@property (nonatomic, assign) SDWebImageOptions options;
+ (nonnull instancetype)sharedImagePrefetcher;
- (nonnull instancetype)initWithImageManager:(nonnull SDWebImageManager *)manager NS_DESIGNATED_INITIALIZER;
- (void)prefetchURLs:(nullable NSArray<NSURL *> *)urls; - (void)prefetchURLs:(nullable NSArray<NSURL *> *)urls progress:(nullable SDWebImagePrefetcherProgressBlock)progressBlock completed:(nullable SDWebImagePrefetcherCompletionBlock)completionBlock;
- (void)cancelPrefetching;
|
SDWebImagePrefetcher还提供了代理来对预下载过程进行监听,如下:
1 2 3 4
| - (void)imagePrefetcher:(nonnull SDWebImagePrefetcher *)imagePrefetcher didPrefetchURL:(nullable NSURL *)imageURL finishedCount:(NSUInteger)finishedCount totalCount:(NSUInteger)totalCount;
- (void)imagePrefetcher:(nonnull SDWebImagePrefetcher *)imagePrefetcher didFinishWithTotalCount:(NSUInteger)totalCount skippedCount:(NSUInteger)skippedCount;
|
二、核心功能
SDWebImage的核心功能类结构如下图所示:
1.缓存管理类SDImageCache
SDImageCache类负责所有网络图片数据的缓存,其从逻辑上分为两级缓存,内存缓存和硬盘缓存。开发者可以使用单例方法来获取默认的SDImageCache实例,也可以使用特殊的Name值来创建缓存实例,常用函数列举如下:
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
| - (void)storeImage:(nullable UIImage *)image forKey:(nullable NSString *)key completion:(nullable SDWebImageNoParamsBlock)completionBlock;
- (void)storeImage:(nullable UIImage *)image forKey:(nullable NSString *)key toDisk:(BOOL)toDisk completion:(nullable SDWebImageNoParamsBlock)completionBlock; - (void)storeImage:(nullable UIImage *)image imageData:(nullable NSData *)imageData forKey:(nullable NSString *)key toDisk:(BOOL)toDisk completion:(nullable SDWebImageNoParamsBlock)completionBlock; - (void)storeImageDataToDisk:(nullable NSData *)imageData forKey:(nullable NSString *)key;
- (void)diskImageExistsWithKey:(nullable NSString *)key completion:(nullable SDWebImageCheckCacheCompletionBlock)completionBlock;
- (nullable UIImage *)imageFromMemoryCacheForKey:(nullable NSString *)key;
- (nullable UIImage *)imageFromDiskCacheForKey:(nullable NSString *)key;
- (nullable UIImage *)imageFromCacheForKey:(nullable NSString *)key;
- (void)removeImageForKey:(nullable NSString *)key withCompletion:(nullable SDWebImageNoParamsBlock)completion; - (void)removeImageForKey:(nullable NSString *)key fromDisk:(BOOL)fromDisk withCompletion:(nullable SDWebImageNoParamsBlock)completion;
- (void)clearMemory;
- (void)deleteOldFilesWithCompletionBlock:(nullable SDWebImageNoParamsBlock)completionBlock;
- (NSUInteger)getSize;
- (NSUInteger)getDiskCount;
|
SDImageCacheConfig用来对缓存进行配置,如下:
1 2 3 4 5 6
| @property (assign, nonatomic) BOOL shouldCacheImagesInMemory;
@property (assign, nonatomic) NSInteger maxCacheAge;
@property (assign, nonatomic) NSUInteger maxCacheSize;
|
2.下载器SDWebImageDownloader
SDWebImageDownloader提供对图片下载的支持管理,其可以配置同时最大下载数量,下载超时等:
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
| @property (assign, nonatomic) NSInteger maxConcurrentDownloads;
@property (readonly, nonatomic) NSUInteger currentDownloadCount;
@property (assign, nonatomic) NSTimeInterval downloadTimeout;
@property (strong, nonatomic, nullable) NSURLCredential *urlCredential;
@property (strong, nonatomic, nullable) NSString *username;
@property (strong, nonatomic, nullable) NSString *password;
- (void)setValue:(nullable NSString *)value forHTTPHeaderField:(nullable NSString *)field;
- (nullable NSString *)valueForHTTPHeaderField:(nullable NSString *)field;
- (nullable SDWebImageDownloadToken *)downloadImageWithURL:(nullable NSURL *)url options:(SDWebImageDownloaderOptions)options progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock completed:(nullable SDWebImageDownloaderCompletedBlock)completedBlock;
- (void)cancel:(nullable SDWebImageDownloadToken *)token;
- (void)cancelAllDownloads;
|
三、应用类别
这个类别用来对按钮设置网络图片。
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
| - (nullable NSURL *)sd_currentImageURL;
- (nullable NSURL *)sd_imageURLForState:(UIControlState)state;
- (void)sd_setImageWithURL:(nullable NSURL *)url forState:(UIControlState)state; - (void)sd_setImageWithURL:(nullable NSURL *)url forState:(UIControlState)state placeholderImage:(nullable UIImage *)placeholder; - (void)sd_setImageWithURL:(nullable NSURL *)url forState:(UIControlState)state placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options; - (void)sd_setImageWithURL:(nullable NSURL *)url forState:(UIControlState)state completed:(nullable SDExternalCompletionBlock)completedBlock; - (void)sd_setImageWithURL:(nullable NSURL *)url forState:(UIControlState)state placeholderImage:(nullable UIImage *)placeholder completed:(nullable SDExternalCompletionBlock)completedBlock; - (void)sd_setImageWithURL:(nullable NSURL *)url forState:(UIControlState)state placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options completed:(nullable SDExternalCompletionBlock)completedBlock;
- (nullable NSURL *)sd_currentBackgroundImageURL; - (nullable NSURL *)sd_backgroundImageURLForState:(UIControlState)state; - (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url forState:(UIControlState)state; - (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url forState:(UIControlState)state placeholderImage:(nullable UIImage *)placeholder; - (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url forState:(UIControlState)state placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options; - (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url forState:(UIControlState)state completed:(nullable SDExternalCompletionBlock)completedBlock; - (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url forState:(UIControlState)state placeholderImage:(nullable UIImage *)placeholder completed:(nullable SDExternalCompletionBlock)completedBlock; - (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url forState:(UIControlState)state placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options completed:(nullable SDExternalCompletionBlock)completedBlock;
- (void)sd_cancelImageLoadForState:(UIControlState)state; - (void)sd_cancelBackgroundImageLoadForState:(UIControlState)state;
|
2.UIImageView+WebCache与UIImageView+HighlightedWebCache
这两个类别的作用都是对UIImageView实例进行图片设置,分别设置正常状态的图片和高亮状态的图片。只举例UIImageView+WebCache中方法如下:
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
| - (void)sd_setImageWithURL:(nullable NSURL *)url; - (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder; - (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options; - (void)sd_setImageWithURL:(nullable NSURL *)url completed:(nullable SDExternalCompletionBlock)completedBlock; - (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder completed:(nullable SDExternalCompletionBlock)completedBlock; - (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options completed:(nullable SDExternalCompletionBlock)completedBlock; - (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock completed:(nullable SDExternalCompletionBlock)completedBlock; - (void)sd_setImageWithPreviousCachedImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock completed:(nullable SDExternalCompletionBlock)completedBlock;
- (void)sd_setAnimationImagesWithURLs:(nonnull NSArray<NSURL *> *)arrayOfURLs;
- (void)sd_cancelCurrentAnimationImagesLoad;
|
关于SDWebImageOptions,它是一个配置枚举:
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
| typedef NS_OPTIONS(NSUInteger, SDWebImageOptions) { SDWebImageRetryFailed = 1 << 0, SDWebImageLowPriority = 1 << 1, SDWebImageCacheMemoryOnly = 1 << 2, SDWebImageProgressiveDownload = 1 << 3, SDWebImageRefreshCached = 1 << 4, SDWebImageContinueInBackground = 1 << 5, SDWebImageHandleCookies = 1 << 6, SDWebImageAllowInvalidSSLCertificates = 1 << 7, SDWebImageHighPriority = 1 << 8, SDWebImageDelayPlaceholder = 1 << 9, SDWebImageTransformAnimatedImage = 1 << 10, SDWebImageScaleDownLargeImages = 1 << 12 };
|