SDWebImage源码解读UIImageView+WebCache
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SDWebImage源码解读UIImageView+WebCache相关的知识,希望对你有一定的参考价值。
前言
这三个分类比较简单,就放在一起解读了。
正文
UIImageView+WebCache
这是UIImageView的分类,旨在使用UIImageView加载图片。
我们看具体代码
1 - (void)sd_setImageWithURL:(nullable NSURL *)url; 2 3 - (void)sd_setImageWithURL:(nullable NSURL *)url 4 placeholderImage:(nullable UIImage *)placeholder; 5 6 - (void)sd_setImageWithURL:(nullable NSURL *)url 7 placeholderImage:(nullable UIImage *)placeholder 8 options:(SDWebImageOptions)options; 9 10 - (void)sd_setImageWithURL:(nullable NSURL *)url 11 completed:(nullable SDExternalCompletionBlock)completedBlock; 12 13 - (void)sd_setImageWithURL:(nullable NSURL *)url 14 placeholderImage:(nullable UIImage *)placeholder 15 completed:(nullable SDExternalCompletionBlock)completedBlock; 16 17 - (void)sd_setImageWithURL:(nullable NSURL *)url 18 placeholderImage:(nullable UIImage *)placeholder 19 options:(SDWebImageOptions)options 20 completed:(nullable SDExternalCompletionBlock)completedBlock; 21 22 - (void)sd_setImageWithURL:(nullable NSURL *)url 23 placeholderImage:(nullable UIImage *)placeholder 24 options:(SDWebImageOptions)options 25 progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock 26 completed:(nullable SDExternalCompletionBlock)completedBlock; 27 28 - (void)sd_setImageWithPreviousCachedImageWithURL:(nullable NSURL *)url 29 placeholderImage:(nullable UIImage *)placeholder 30 options:(SDWebImageOptions)options 31 progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock 32 completed:(nullable SDExternalCompletionBlock)completedBlock;
跳转到这几个方法的具体实现,显而易见,它们最终调用UIView+WebCache的这个方法(这个方法随后解释):
- (void)sd_internalSetImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options operationKey:(nullable NSString *)operationKey setImageBlock:(nullable SDSetImageBlock)setImageBlock progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock completed:(nullable SDExternalCompletionBlock)completedBlock;
有一个点稍微注意下:
划线的三目运算符,如果问号之后的第一个参数未填写,则默认返回条件本身。
那么接下来,这个类还有两个方法需要解读:
1 /** 2 * Download an array of images and starts them in an animation loop 3 * 4 * @param arrayOfURLs An array of NSURL 5 */ 6 - (void)sd_setAnimationImagesWithURLs:(nonnull NSArray<NSURL *> *)arrayOfURLs; 7 8 - (void)sd_cancelCurrentAnimationImagesLoad;
根据方法声明,我们了解到,这是用来加载UIImageView的帧动画图片数组。我们直接看方法的具体实现:
- (void)sd_setAnimationImagesWithURLs:(nonnull NSArray<NSURL *> *)arrayOfURLs { [self sd_cancelCurrentAnimationImagesLoad]; __weak __typeof(self)wself = self; NSMutableArray<id<SDWebImageOperation>> *operationsArray = [[NSMutableArray alloc] init]; for (NSURL *logoImageURL in arrayOfURLs) { id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:logoImageURL options:0 progress:nil completed:^(UIImage *image, NSData *data, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { if (!wself) return; dispatch_main_async_safe(^{ __strong UIImageView *sself = wself; [sself stopAnimating]; if (sself && image) { NSMutableArray<UIImage *> *currentImages = [[sself animationImages] mutableCopy]; if (!currentImages) { currentImages = [[NSMutableArray alloc] init]; } [currentImages addObject:image]; sself.animationImages = currentImages; [sself setNeedsLayout]; } [sself startAnimating]; }); }]; [operationsArray addObject:operation]; } [self sd_setImageLoadOperation:[operationsArray copy] forKey:@"UIImageViewAnimationImages"]; } - (void)sd_cancelCurrentAnimationImagesLoad { [self sd_cancelImageLoadOperationWithKey:@"UIImageViewAnimationImages"]; }
我们可以看到,这个方法遍历图片URL数组,然后使用SDWebImageManager的方法,将每个图片加载的操作放入operation数组中,然后调用:
[self sd_setImageLoadOperation:[operationsArray copy] forKey:@"UIImageViewAnimationImages"];
这个方法是UIView+WebCacheOperation,将所有操作用字典进行存储。
在这个方法内部,我们看到“dispatch_main_async_safe”
1 #ifndef dispatch_main_async_safe 2 #define dispatch_main_async_safe(block)3 if (strcmp(dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL), dispatch_queue_get_label(dispatch_get_main_queue())) == 0) {4 block();5 } else {6 dispatch_async(dispatch_get_main_queue(), block);7 } 8 #endif
这是SDWebImageCompat类中的宏定义。目的是保证线程安全,保证block中的代码在主线程中执行。当图片一旦被下载,就在主线程更新UIimageview。
- (void)sd_cancelCurrentAnimationImagesLoad { [self sd_cancelImageLoadOperationWithKey:@"UIImageViewAnimationImages"]; }
最后一个方法,是取消当前正在加载的AnimationImages操作
以上是关于SDWebImage源码解读UIImageView+WebCache的主要内容,如果未能解决你的问题,请参考以下文章
SDWebImage源码阅读(十七)UIImageView+HighlightedWebCache