SDWebImage源码阅读(十六)UIButton+WebCache

  这是 SDWebImage 里面针对 UIButton 添加图片添加的一个 WebCache 分类。

 .h

1 /**
2  * Get the current image URL.
3  */
4 - (nullable NSURL *)sd_currentImageURL;

  获得当前图像的 URL。

1 /**
2  * Get the image URL for a control state.
3  * 
4  * @param state Which state you want to know the URL for. The values are described in UIControlState.
5  */
6 - (nullable NSURL *)sd_imageURLForState:(UIControlState)state;

  根据 UIControlState 获得指定的图像的 URL。

 1 /**
 2  * Set the imageView `image` with an `url`.
 3  *
 4  * The download is asynchronous and cached.
 5  *
 6  * @param url   The url for the image.
 7  * @param state The state that uses the specified title. The values are described in UIControlState.
 8  */
 9 - (void)sd_setImageWithURL:(nullable NSURL *)url
10                   forState:(UIControlState)state;

  根据 state 给 UIButton 设置指定状态的 UIImage。

 1 /**
 2  * Set the imageView `image` with an `url` and a placeholder.
 3  *
 4  * The download is asynchronous and cached.
 5  *
 6  * @param url         The url for the image.
 7  * @param state       The state that uses the specified title. The values are described in UIControlState.
 8  * @param placeholder The image to be set initially, until the image request finishes.
 9  * @see sd_setImageWithURL:placeholderImage:options:
10  */
11 - (void)sd_setImageWithURL:(nullable NSURL *)url
12                   forState:(UIControlState)state
13           placeholderImage:(nullable UIImage *)placeholder;

  添加一个在图片下载完成之前的占位图。

 1 /**
 2  * Set the imageView `image` with an `url`, placeholder and custom options.
 3  *
 4  * The download is asynchronous and cached.
 5  *
 6  * @param url         The url for the image.
 7  * @param state       The state that uses the specified title. The values are described in UIControlState.
 8  * @param placeholder The image to be set initially, until the image request finishes.
 9  * @param options     The options to use when downloading the image. @see SDWebImageOptions for the possible values.
10  */
11 - (void)sd_setImageWithURL:(nullable NSURL *)url
12                   forState:(UIControlState)state
13           placeholderImage:(nullable UIImage *)placeholder
14                    options:(SDWebImageOptions)options;

  添加一个下载选择 SDWebImageOptions。

 1 /**
 2  * Set the imageView `image` with an `url`.
 3  *
 4  * The download is asynchronous and cached.
 5  *
 6  * @param url            The url for the image.
 7  * @param state          The state that uses the specified title. The values are described in UIControlState.
 8  * @param completedBlock A block called when operation has been completed. This block has no return value
 9  *                       and takes the requested UIImage as first parameter. In case of error the image parameter
10  *                       is nil and the second parameter may contain an NSError. The third parameter is a Boolean
11  *                       indicating if the image was retrieved from the local cache or from the network.
12  *                       The fourth parameter is the original image url.
13  */
14 - (void)sd_setImageWithURL:(nullable NSURL *)url
15                   forState:(UIControlState)state
16                  completed:(nullable SDExternalCompletionBlock)completedBlock;

   添加一个图片下载完成的 block。

1 typedef void(^SDExternalCompletionBlock)(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL);
 1 /**
 2  * Set the imageView `image` with an `url`, placeholder.
 3  *
 4  * The download is asynchronous and cached.
 5  *
 6  * @param url            The url for the image.
 7  * @param state          The state that uses the specified title. The values are described in UIControlState.
 8  * @param placeholder    The image to be set initially, until the image request finishes.
 9  * @param completedBlock A block called when operation has been completed. This block has no return value
10  *                       and takes the requested UIImage as first parameter. In case of error the image parameter
11  *                       is nil and the second parameter may contain an NSError. The third parameter is a Boolean
12  *                       indicating if the image was retrieved from the local cache or from the network.
13  *                       The fourth parameter is the original image url.
14  */
15 - (void)sd_setImageWithURL:(nullable NSURL *)url
16                   forState:(UIControlState)state
17           placeholderImage:(nullable UIImage *)placeholder
18                  completed:(nullable SDExternalCompletionBlock)completedBlock;

  添加一个占位图片。

 1 /**
 2  * Set the imageView `image` with an `url`, placeholder and custom options.
 3  *
 4  * The download is asynchronous and cached.
 5  *
 6  * @param url            The url for the image.
 7  * @param state          The state that uses the specified title. The values are described in UIControlState.
 8  * @param placeholder    The image to be set initially, until the image request finishes.
 9  * @param options        The options to use when downloading the image. @see SDWebImageOptions for the possible values.
10  * @param completedBlock A block called when operation has been completed. This block has no return value
11  *                       and takes the requested UIImage as first parameter. In case of error the image parameter
12  *                       is nil and the second parameter may contain an NSError. The third parameter is a Boolean
13  *                       indicating if the image was retrieved from the local cache or from the network.
14  *                       The fourth parameter is the original image url.
15  */
16 - (void)sd_setImageWithURL:(nullable NSURL *)url
17                   forState:(UIControlState)state
18           placeholderImage:(nullable UIImage *)placeholder
19                    options:(SDWebImageOptions)options
20                  completed:(nullable SDExternalCompletionBlock)completedBlock;

  添加一个下载选项 SDWebImageOptions。

 Background image

  和上面的方法类似......

 Cancel

1 /**
2  * Cancel the current image download
3  */
4 - (void)sd_cancelImageLoadForState:(UIControlState)state;

  取消当前的图片下载。

1 /**
2  * Cancel the current backgroundImage download
3  */
4 - (void)sd_cancelBackgroundImageLoadForState:(UIControlState)state;

  取消当前的图片的后台下载。

 .m

1 static char imageURLStorageKey;

 2 typedef NSMutableDictionary<NSNumber *, NSURL *> SDStateImageURLDictionary;

  用于给 UIButton 关联对象使用的关键字,关联对象是 SDStateImageURLDictionary。

  定义了一个 key 是 NSNumber,value 是 NSURL 的可变字典。

1 - (SDStateImageURLDictionary *)imageURLStorage {
2     SDStateImageURLDictionary *storage = objc_getAssociatedObject(self, &imageURLStorageKey);
3     if (!storage) {
4         storage = [NSMutableDictionary dictionary];
5         objc_setAssociatedObject(self, &imageURLStorageKey, storage, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
6     }
7 
8     return storage;
9 }

  给 UIButton 添加一个关联对象,用于记录 UIButton 在不同的 UIControlState 状态下的图片的 URL。

 1 - (nullable NSURL *)sd_currentImageURL {
 2     NSURL *url = self.imageURLStorage[@(self.state)];
 3 
 4     if (!url) {
 5         url = self.imageURLStorage[@(UIControlStateNormal)];
 6     }
 7 
 8     return url;
 9 }
10 
11 - (nullable NSURL *)sd_imageURLForState:(UIControlState)state {
12     return self.imageURLStorage[@(state)];
13 }

  获取 UIButton 默认状态下的 UIImage 的 URL,和指定状态下的 UIImage 的 URL。

 1 - (void)sd_setImageWithURL:(nullable NSURL *)url forState:(UIControlState)state {
 2     [self sd_setImageWithURL:url forState:state placeholderImage:nil options:0 completed:nil];
 3 }
 4 
 5 - (void)sd_setImageWithURL:(nullable NSURL *)url forState:(UIControlState)state placeholderImage:(nullable UIImage *)placeholder {
 6     [self sd_setImageWithURL:url forState:state placeholderImage:placeholder options:0 completed:nil];
 7 }
 8 
 9 - (void)sd_setImageWithURL:(nullable NSURL *)url forState:(UIControlState)state placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options {
10     [self sd_setImageWithURL:url forState:state placeholderImage:placeholder options:options completed:nil];
11 }
12 
13 - (void)sd_setImageWithURL:(nullable NSURL *)url forState:(UIControlState)state completed:(nullable SDExternalCompletionBlock)completedBlock {
14     [self sd_setImageWithURL:url forState:state placeholderImage:nil options:0 completed:completedBlock];
15 }
16 
17 - (void)sd_setImageWithURL:(nullable NSURL *)url forState:(UIControlState)state placeholderImage:(nullable UIImage *)placeholder completed:(nullable SDExternalCompletionBlock)completedBlock {
18     [self sd_setImageWithURL:url forState:state placeholderImage:placeholder options:0 completed:completedBlock];
19 }

  占位图片默认是 nil,下载选项默认是 0,即没有下载选项(SDWebImageOptions 是从 1 开始的),默认 completedBlock 是 nil。

 1 - (void)sd_setImageWithURL:(nullable NSURL *)url
 2                   forState:(UIControlState)state
 3           placeholderImage:(nullable UIImage *)placeholder
 4                    options:(SDWebImageOptions)options
 5                  completed:(nullable SDExternalCompletionBlock)completedBlock {
 6     if (!url) {
 7         [self.imageURLStorage removeObjectForKey:@(state)];
 8         return;
 9     }
10     
11     self.imageURLStorage[@(state)] = url;
12     
13     __weak typeof(self)weakSelf = self;
14     [self sd_internalSetImageWithURL:url
15                     placeholderImage:placeholder
16                              options:options
17                         operationKey:[NSString stringWithFormat:@"UIButtonImageOperation%@", @(state)]
18                        setImageBlock:^(UIImage *image, NSData *imageData) {
19                            [weakSelf setImage:image forState:state];
20                        }
21                             progress:nil
22                            completed:completedBlock];
23 }

  这个才是 UIButton 下载图片方法的主体。

  如果 url 不存在则直接删除  self.imageURLStorage 里面指定的 UIControlState 的图片的 URL。

  如果 state 和 url 都存在则把 url 和 state 对应存入 self.imageURLStorage 里面。

  调用 UIView 的 WebCache 分类里面的下载图片的方法。

1 [NSString stringWithFormat:@"UIButtonImageOperation%@", @(state)]
 1 - (void)sd_setImageLoadOperation:(id<SDWebImageOperation>)operation forState:(UIControlState)state {
 2     [self sd_setImageLoadOperation:operation forKey:[NSString stringWithFormat:@"UIButtonImageOperation%@", @(state)]];
 3 }
 4 
 5 - (void)sd_cancelImageLoadForState:(UIControlState)state {
 6     [self sd_cancelImageLoadOperationWithKey:[NSString stringWithFormat:@"UIButtonImageOperation%@", @(state)]];
 7 }
 8 
 9 - (void)sd_setBackgroundImageLoadOperation:(id<SDWebImageOperation>)operation forState:(UIControlState)state {
10     [self sd_setImageLoadOperation:operation forKey:[NSString stringWithFormat:@"UIButtonBackgroundImageOperation%@", @(state)]];
11 }
12 
13 - (void)sd_cancelBackgroundImageLoadForState:(UIControlState)state {
14     [self sd_cancelImageLoadOperationWithKey:[NSString stringWithFormat:@"UIButtonBackgroundImageOperation%@", @(state)]];
15 }

  调取 UIView 的 WebCacheOperation 里面的方法。

END

posted @ 2017-06-11 10:03  鳄鱼不怕牙医不怕  阅读(347)  评论(0编辑  收藏  举报