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