原始碼閱讀:SDWebImage(二十)——UIButton+WebCache

堯少羽發表於2018-07-27

該文章閱讀的SDWebImage的版本為4.3.3。

這個分類提供了為UIButton設定網路影像的快捷方法。

1.公共方法

1.1.設定image的方法

/**
 獲取當前影像連結地址
 */
- (nullable NSURL *)sd_currentImageURL;
複製程式碼
/**
 獲取指定狀態影像連結地址
 */
- (nullable NSURL *)sd_imageURLForState:(UIControlState)state;
複製程式碼
/**
 設定指定狀態的影像連結地址
 */
- (void)sd_setImageWithURL:(nullable NSURL *)url
                  forState:(UIControlState)state NS_REFINED_FOR_SWIFT;
複製程式碼
/**
 設定指定狀態的影像連結地址和佔點陣圖
 */
- (void)sd_setImageWithURL:(nullable NSURL *)url
                  forState:(UIControlState)state
          placeholderImage:(nullable UIImage *)placeholder NS_REFINED_FOR_SWIFT;
複製程式碼
/**
 設定指定狀態的影像連結地址和佔點陣圖以及可選項
 */
- (void)sd_setImageWithURL:(nullable NSURL *)url
                  forState:(UIControlState)state
          placeholderImage:(nullable UIImage *)placeholder
                   options:(SDWebImageOptions)options NS_REFINED_FOR_SWIFT;
複製程式碼
/**
 設定指定狀態的影像連結地址和完成回撥
 */
- (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 NS_REFINED_FOR_SWIFT;
複製程式碼
/**
 設定指定狀態的影像連結地址、佔點陣圖、可選項以及完成回撥
 */
- (void)sd_setImageWithURL:(nullable NSURL *)url
                  forState:(UIControlState)state
          placeholderImage:(nullable UIImage *)placeholder
                   options:(SDWebImageOptions)options
                 completed:(nullable SDExternalCompletionBlock)completedBlock;
複製程式碼

1.2.設定background image的方法

/**
 獲取當前背景影像連結地址
 */
- (nullable NSURL *)sd_currentBackgroundImageURL;

/**
 獲取指定狀態背景影像連結地址
 */
- (nullable NSURL *)sd_backgroundImageURLForState:(UIControlState)state;

/**
 設定指定狀態的背景影像連結地址
 */
- (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url
                            forState:(UIControlState)state NS_REFINED_FOR_SWIFT;
複製程式碼
/**
 設定指定狀態的背景影像連結地址和佔點陣圖
 */
- (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url
                            forState:(UIControlState)state
                    placeholderImage:(nullable UIImage *)placeholder NS_REFINED_FOR_SWIFT;
複製程式碼
/**
 設定指定狀態的背景影像連結地址和佔點陣圖以及可選項
 */
- (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url
                            forState:(UIControlState)state
                    placeholderImage:(nullable UIImage *)placeholder
                             options:(SDWebImageOptions)options NS_REFINED_FOR_SWIFT;
複製程式碼
/**
 設定指定狀態的背景影像連結地址和佔點陣圖以及完成回撥
 */
- (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 NS_REFINED_FOR_SWIFT;
複製程式碼
/**
 設定指定狀態的背景影像連結地址、佔點陣圖、可選項以及完成回撥
 */
- (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url
                            forState:(UIControlState)state
                    placeholderImage:(nullable UIImage *)placeholder
                             options:(SDWebImageOptions)options
                           completed:(nullable SDExternalCompletionBlock)completedBlock;

複製程式碼

1.3.取消網路影像載入的方法

/**
 取消指定狀態當前影像的網路載入
 */
- (void)sd_cancelImageLoadForState:(UIControlState)state;
複製程式碼
/**
 取消指定狀態當前背景影像的網路載入
 */
- (void)sd_cancelBackgroundImageLoadForState:(UIControlState)state;
複製程式碼

2.私有靜態函式

/**
 獲取指定狀態的影像連結鍵
 */
static inline NSString * imageURLKeyForState(UIControlState state) {
    return [NSString stringWithFormat:@"image_%lu", (unsigned long)state];
}
複製程式碼
/**
 獲取指定狀態的背景影像連結鍵
 */
static inline NSString * backgroundImageURLKeyForState(UIControlState state) {
    return [NSString stringWithFormat:@"backgroundImage_%lu", (unsigned long)state];
}
複製程式碼
/**
 獲取指定狀態的影像選項鍵
 */
static inline NSString * imageOperationKeyForState(UIControlState state) {
    return [NSString stringWithFormat:@"UIButtonImageOperation%lu", (unsigned long)state];
}
複製程式碼
/**
 獲取指定狀態的背景影像選項鍵
 */
static inline NSString * backgroundImageOperationKeyForState(UIControlState state) {
    return [NSString stringWithFormat:@"UIButtonBackgroundImageOperation%lu", (unsigned long)state];
}
複製程式碼

3.私有方法

/**
 獲取儲存影像連結的字典物件
 */
- (SDStateImageURLDictionary *)sd_imageURLStorage {
    SDStateImageURLDictionary *storage = objc_getAssociatedObject(self, &imageURLStorageKey);
    if (!storage) {
        storage = [NSMutableDictionary dictionary];
        objc_setAssociatedObject(self, &imageURLStorageKey, storage, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }

    return storage;
}
複製程式碼

4.實現

4.1.設定image的方法實現

- (nullable NSURL *)sd_currentImageURL {
    // 獲取當前狀態的影像地址
    NSURL *url = self.sd_imageURLStorage[imageURLKeyForState(self.state)];

    // 如果沒有就獲取普通狀態的影像地址
    if (!url) {
        url = self.sd_imageURLStorage[imageURLKeyForState(UIControlStateNormal)];
    }

    return url;
}

- (nullable NSURL *)sd_imageURLForState:(UIControlState)state {
    // 獲取指定狀態的影像地址
    return self.sd_imageURLStorage[imageURLKeyForState(state)];
}

- (void)sd_setImageWithURL:(nullable NSURL *)url forState:(UIControlState)state {
    // 呼叫全能方法
    [self sd_setImageWithURL:url forState:state placeholderImage:nil options:0 completed:nil];
}

- (void)sd_setImageWithURL:(nullable NSURL *)url forState:(UIControlState)state placeholderImage:(nullable UIImage *)placeholder {
    // 呼叫全能方法
    [self sd_setImageWithURL:url forState:state placeholderImage:placeholder options:0 completed:nil];
}

- (void)sd_setImageWithURL:(nullable NSURL *)url forState:(UIControlState)state placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options {
    [self sd_setImageWithURL:url forState:state placeholderImage:placeholder options:options completed:nil];
}

- (void)sd_setImageWithURL:(nullable NSURL *)url forState:(UIControlState)state completed:(nullable SDExternalCompletionBlock)completedBlock {
    // 呼叫全能方法
    [self sd_setImageWithURL:url forState:state placeholderImage:nil options:0 completed:completedBlock];
}

- (void)sd_setImageWithURL:(nullable NSURL *)url forState:(UIControlState)state placeholderImage:(nullable UIImage *)placeholder completed:(nullable SDExternalCompletionBlock)completedBlock {
    // 呼叫全能方法
    [self sd_setImageWithURL:url forState:state placeholderImage:placeholder options:0 completed:completedBlock];
}

- (void)sd_setImageWithURL:(nullable NSURL *)url
                  forState:(UIControlState)state
          placeholderImage:(nullable UIImage *)placeholder
                   options:(SDWebImageOptions)options
                 completed:(nullable SDExternalCompletionBlock)completedBlock {
    if (!url) {
        // 不傳連結就移除掉指定狀態對應的值
        [self.sd_imageURLStorage removeObjectForKey:imageURLKeyForState(state)];
    } else {
        // 根據指定狀態儲存連結
        self.sd_imageURLStorage[imageURLKeyForState(state)] = url;
    }
    
    // 呼叫UIView+WebCache分類方法載入影像
    __weak typeof(self)weakSelf = self;
    [self sd_internalSetImageWithURL:url
                    placeholderImage:placeholder
                             options:options
                        operationKey:imageOperationKeyForState(state)
                       setImageBlock:^(UIImage *image, NSData *imageData) {
                           [weakSelf setImage:image forState:state];
                       }
                            progress:nil
                           completed:completedBlock];
}
複製程式碼

4.2.設定background image的方法實現

- (nullable NSURL *)sd_currentBackgroundImageURL {
    // 獲取當前狀態的背景影像地址
    NSURL *url = self.sd_imageURLStorage[backgroundImageURLKeyForState(self.state)];
    
    // 如果沒有就獲取普通狀態的背景影像地址
    if (!url) {
        url = self.sd_imageURLStorage[backgroundImageURLKeyForState(UIControlStateNormal)];
    }
    
    return url;
}

- (nullable NSURL *)sd_backgroundImageURLForState:(UIControlState)state {
    // 獲取指定狀態的背景影像地址
    return self.sd_imageURLStorage[backgroundImageURLKeyForState(state)];
}

- (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url forState:(UIControlState)state {
    // 呼叫全能方法
    [self sd_setBackgroundImageWithURL:url forState:state placeholderImage:nil options:0 completed:nil];
}

- (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url forState:(UIControlState)state placeholderImage:(nullable UIImage *)placeholder {
    // 呼叫全能方法
    [self sd_setBackgroundImageWithURL:url forState:state placeholderImage:placeholder options:0 completed:nil];
}

- (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url forState:(UIControlState)state placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options {
    // 呼叫全能方法
    [self sd_setBackgroundImageWithURL:url forState:state placeholderImage:placeholder options:options completed:nil];
}

- (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url forState:(UIControlState)state completed:(nullable SDExternalCompletionBlock)completedBlock {
    // 呼叫全能方法
    [self sd_setBackgroundImageWithURL:url forState:state placeholderImage:nil options:0 completed:completedBlock];
}

- (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url forState:(UIControlState)state placeholderImage:(nullable UIImage *)placeholder completed:(nullable SDExternalCompletionBlock)completedBlock {
    // 呼叫全能方法
    [self sd_setBackgroundImageWithURL:url forState:state placeholderImage:placeholder options:0 completed:completedBlock];
}

- (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url
                            forState:(UIControlState)state
                    placeholderImage:(nullable UIImage *)placeholder
                             options:(SDWebImageOptions)options
                           completed:(nullable SDExternalCompletionBlock)completedBlock {
    if (!url) {
        // 不傳連結就移除掉指定狀態對應的值
        [self.sd_imageURLStorage removeObjectForKey:backgroundImageURLKeyForState(state)];
    } else {
        // 根據指定狀態儲存連結
        self.sd_imageURLStorage[backgroundImageURLKeyForState(state)] = url;
    }
    
    // 呼叫UIView+WebCache分類方法載入背景影像
    __weak typeof(self)weakSelf = self;
    [self sd_internalSetImageWithURL:url
                    placeholderImage:placeholder
                             options:options
                        operationKey:backgroundImageOperationKeyForState(state)
                       setImageBlock:^(UIImage *image, NSData *imageData) {
                           [weakSelf setBackgroundImage:image forState:state];
                       }
                            progress:nil
                           completed:completedBlock];
}
複製程式碼

4.3.取消網路影像載入的方法實現

- (void)sd_cancelImageLoadForState:(UIControlState)state {
    // 取消指定key的影像載入操作
    [self sd_cancelImageLoadOperationWithKey:imageOperationKeyForState(state)];
}

- (void)sd_cancelBackgroundImageLoadForState:(UIControlState)state {
    // 取消指定key的背景影像載入操作
    [self sd_cancelImageLoadOperationWithKey:backgroundImageOperationKeyForState(state)];
}
複製程式碼

原始碼閱讀系列:SDWebImage

原始碼閱讀:SDWebImage(一)——從使用入手

原始碼閱讀:SDWebImage(二)——SDWebImageCompat

原始碼閱讀:SDWebImage(三)——NSData+ImageContentType

原始碼閱讀:SDWebImage(四)——SDWebImageCoder

原始碼閱讀:SDWebImage(五)——SDWebImageFrame

原始碼閱讀:SDWebImage(六)——SDWebImageCoderHelper

原始碼閱讀:SDWebImage(七)——SDWebImageImageIOCoder

原始碼閱讀:SDWebImage(八)——SDWebImageGIFCoder

原始碼閱讀:SDWebImage(九)——SDWebImageCodersManager

原始碼閱讀:SDWebImage(十)——SDImageCacheConfig

原始碼閱讀:SDWebImage(十一)——SDImageCache

原始碼閱讀:SDWebImage(十二)——SDWebImageDownloaderOperation

原始碼閱讀:SDWebImage(十三)——SDWebImageDownloader

原始碼閱讀:SDWebImage(十四)——SDWebImageManager

原始碼閱讀:SDWebImage(十五)——SDWebImagePrefetcher

原始碼閱讀:SDWebImage(十六)——SDWebImageTransition

原始碼閱讀:SDWebImage(十七)——UIView+WebCacheOperation

原始碼閱讀:SDWebImage(十八)——UIView+WebCache

原始碼閱讀:SDWebImage(十九)——UIImage+ForceDecode/UIImage+GIF/UIImage+MultiFormat

原始碼閱讀:SDWebImage(二十)——UIButton+WebCache

原始碼閱讀:SDWebImage(二十一)——UIImageView+WebCache/UIImageView+HighlightedWebCache

相關文章