/* * This file is part of the SDWebImage package. * (c) Olivier Poitrey * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ #import "UIButton+WebCache.h" #if SD_UIKIT #import "objc/runtime.h" #import "UIView+WebCacheOperation.h" #import "UIView+WebCache.h" static char imageURLStorageKey; typedef NSMutableDictionary SDStateImageURLDictionary; 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]; } @implementation UIButton (WebCache) #pragma mark - 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; } __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]; } #pragma mark - 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; } __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]; } #pragma mark - Cancel - (void)sd_cancelImageLoadForState:(UIControlState)state { [self sd_cancelImageLoadOperationWithKey:imageOperationKeyForState(state)]; } - (void)sd_cancelBackgroundImageLoadForState:(UIControlState)state { [self sd_cancelImageLoadOperationWithKey:backgroundImageOperationKeyForState(state)]; } #pragma mark - Private - (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; } @end #endif