標籤:ext nload 需要 ini ade nal return 取消 ring
前言
這三個分類比較簡單,就放在一起解讀了。
本文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 *)url11 completed:(nullable SDExternalCompletionBlock)completedBlock;12 13 - (void)sd_setImageWithURL:(nullable NSURL *)url14 placeholderImage:(nullable UIImage *)placeholder15 completed:(nullable SDExternalCompletionBlock)completedBlock;16 17 - (void)sd_setImageWithURL:(nullable NSURL *)url18 placeholderImage:(nullable UIImage *)placeholder19 options:(SDWebImageOptions)options20 completed:(nullable SDExternalCompletionBlock)completedBlock;21 22 - (void)sd_setImageWithURL:(nullable NSURL *)url23 placeholderImage:(nullable UIImage *)placeholder24 options:(SDWebImageOptions)options25 progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock26 completed:(nullable SDExternalCompletionBlock)completedBlock;27 28 - (void)sd_setImageWithPreviousCachedImageWithURL:(nullable NSURL *)url29 placeholderImage:(nullable UIImage *)placeholder30 options:(SDWebImageOptions)options31 progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock32 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 loop3 *4 * @param arrayOfURLs An array of NSURL5 */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_safe2 #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