From 4c18545dbcb3af2d55d06a624dd7a7406d019b37 Mon Sep 17 00:00:00 2001 From: Whirlwind Date: Thu, 19 Jun 2014 22:46:37 +0800 Subject: [PATCH] Refactor the cancel logic --- SDWebImage.xcodeproj/project.pbxproj | 16 ++++++ SDWebImage/MKAnnotationView+WebCache.m | 11 ++-- SDWebImage/UIButton+WebCache.h | 9 +++- SDWebImage/UIButton+WebCache.m | 30 ++++++----- SDWebImage/UIImageView+HighlightedWebCache.h | 7 ++- SDWebImage/UIImageView+HighlightedWebCache.m | 12 +++-- SDWebImage/UIImageView+WebCache.h | 2 +- SDWebImage/UIImageView+WebCache.m | 27 +++------- SDWebImage/UIView+WebCacheOperation.h | 20 +++++++ SDWebImage/UIView+WebCacheOperation.m | 55 ++++++++++++++++++++ 10 files changed, 141 insertions(+), 48 deletions(-) create mode 100644 SDWebImage/UIView+WebCacheOperation.h create mode 100644 SDWebImage/UIView+WebCacheOperation.m diff --git a/SDWebImage.xcodeproj/project.pbxproj b/SDWebImage.xcodeproj/project.pbxproj index 5fe4baa6..a6cf909b 100644 --- a/SDWebImage.xcodeproj/project.pbxproj +++ b/SDWebImage.xcodeproj/project.pbxproj @@ -193,6 +193,12 @@ A18A6CC8172DC28500419892 /* UIImage+GIF.h in Headers */ = {isa = PBXBuildFile; fileRef = A18A6CC5172DC28500419892 /* UIImage+GIF.h */; }; A18A6CC9172DC28500419892 /* UIImage+GIF.m in Sources */ = {isa = PBXBuildFile; fileRef = A18A6CC6172DC28500419892 /* UIImage+GIF.m */; }; A18A6CCA172DC28500419892 /* UIImage+GIF.m in Sources */ = {isa = PBXBuildFile; fileRef = A18A6CC6172DC28500419892 /* UIImage+GIF.m */; }; + AB615303192DA24600A2D8E9 /* UIView+WebCacheOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = AB615301192DA24600A2D8E9 /* UIView+WebCacheOperation.h */; }; + AB615304192DA24600A2D8E9 /* UIView+WebCacheOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = AB615301192DA24600A2D8E9 /* UIView+WebCacheOperation.h */; }; + AB615305192DA24600A2D8E9 /* UIView+WebCacheOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = AB615301192DA24600A2D8E9 /* UIView+WebCacheOperation.h */; }; + AB615306192DA24600A2D8E9 /* UIView+WebCacheOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = AB615302192DA24600A2D8E9 /* UIView+WebCacheOperation.m */; }; + AB615307192DA24600A2D8E9 /* UIView+WebCacheOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = AB615302192DA24600A2D8E9 /* UIView+WebCacheOperation.m */; }; + AB615308192DA24600A2D8E9 /* UIView+WebCacheOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = AB615302192DA24600A2D8E9 /* UIView+WebCacheOperation.m */; }; ABBE71A718C43B4D00B75E91 /* UIImageView+HighlightedWebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = ABBE71A518C43B4D00B75E91 /* UIImageView+HighlightedWebCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; ABBE71A818C43B4D00B75E91 /* UIImageView+HighlightedWebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = ABBE71A618C43B4D00B75E91 /* UIImageView+HighlightedWebCache.m */; }; ABBE71A918C43B5800B75E91 /* UIImageView+HighlightedWebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = ABBE71A518C43B4D00B75E91 /* UIImageView+HighlightedWebCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -290,6 +296,8 @@ 5DA509F3187B68E7002FEB5C /* random.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = random.h; path = Vendors/libwebp/src/utils/random.h; sourceTree = ""; }; A18A6CC5172DC28500419892 /* UIImage+GIF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+GIF.h"; sourceTree = ""; }; A18A6CC6172DC28500419892 /* UIImage+GIF.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+GIF.m"; sourceTree = ""; }; + AB615301192DA24600A2D8E9 /* UIView+WebCacheOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+WebCacheOperation.h"; sourceTree = ""; }; + AB615302192DA24600A2D8E9 /* UIView+WebCacheOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+WebCacheOperation.m"; sourceTree = ""; }; ABBE71A518C43B4D00B75E91 /* UIImageView+HighlightedWebCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImageView+HighlightedWebCache.h"; sourceTree = ""; }; ABBE71A618C43B4D00B75E91 /* UIImageView+HighlightedWebCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImageView+HighlightedWebCache.m"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -392,6 +400,8 @@ 53922D94148C56230056699D /* UIButton+WebCache.m */, 53922D95148C56230056699D /* UIImageView+WebCache.h */, 53922D96148C56230056699D /* UIImageView+WebCache.m */, + AB615301192DA24600A2D8E9 /* UIView+WebCacheOperation.h */, + AB615302192DA24600A2D8E9 /* UIView+WebCacheOperation.m */, ); name = Categories; sourceTree = ""; @@ -532,6 +542,7 @@ 53EDFCB317625CD800698166 /* quant_levels_dec.h in Headers */, 53EDFCBA17625D1900698166 /* dsp.h in Headers */, 53EDFCC617625DB200698166 /* bit_reader.h in Headers */, + AB615305192DA24600A2D8E9 /* UIView+WebCacheOperation.h in Headers */, 53EDFCCC17625DD700698166 /* color_cache.h in Headers */, 53EDFCD217625DFA00698166 /* lossless.h in Headers */, 53EDFCE417625EB100698166 /* yuv.h in Headers */, @@ -559,6 +570,7 @@ 530E49E816464C25002868E7 /* SDWebImageOperation.h in Headers */, 530E49EA16464C7C002868E7 /* SDWebImageDownloaderOperation.h in Headers */, ABBE71A718C43B4D00B75E91 /* UIImageView+HighlightedWebCache.h in Headers */, + AB615303192DA24600A2D8E9 /* UIView+WebCacheOperation.h in Headers */, A18A6CC7172DC28500419892 /* UIImage+GIF.h in Headers */, 53EDFB8A17623F7C00698166 /* UIImage+MultiFormat.h in Headers */, ); @@ -591,6 +603,7 @@ 537D95B417ECC1FE0097C263 /* bit_reader.h in Headers */, 537D95B517ECC1FE0097C263 /* color_cache.h in Headers */, 537D95B617ECC1FE0097C263 /* lossless.h in Headers */, + AB615304192DA24600A2D8E9 /* UIView+WebCacheOperation.h in Headers */, 537D95B717ECC1FE0097C263 /* alpha_processing.h in Headers */, 5DA509F5187B68E7002FEB5C /* random.h in Headers */, 537D95B817ECC1FE0097C263 /* yuv.h in Headers */, @@ -749,6 +762,7 @@ A18A6CCA172DC28500419892 /* UIImage+GIF.m in Sources */, 53EDFB8D17623F7C00698166 /* UIImage+MultiFormat.m in Sources */, 53EDFB961762547D00698166 /* UIImage+WebP.m in Sources */, + AB615308192DA24600A2D8E9 /* UIView+WebCacheOperation.m in Sources */, ABBE71AC18C43B6000B75E91 /* UIImageView+HighlightedWebCache.m in Sources */, 53EDFC9517625BE300698166 /* webp.c in Sources */, 53EDFC9D17625C1100698166 /* vp8l.c in Sources */, @@ -794,6 +808,7 @@ 530E49EC16464C84002868E7 /* SDWebImageDownloaderOperation.m in Sources */, 53406750167780C40042B59E /* SDWebImageCompat.m in Sources */, A18A6CC9172DC28500419892 /* UIImage+GIF.m in Sources */, + AB615306192DA24600A2D8E9 /* UIView+WebCacheOperation.m in Sources */, 5D5B9145188EE8DD006D06BD /* NSData+ImageContentType.m in Sources */, 53EDFB8C17623F7C00698166 /* UIImage+MultiFormat.m in Sources */, ABBE71A818C43B4D00B75E91 /* UIImageView+HighlightedWebCache.m in Sources */, @@ -805,6 +820,7 @@ buildActionMask = 2147483647; files = ( 537D957517ECC1FE0097C263 /* SDImageCache.m in Sources */, + AB615307192DA24600A2D8E9 /* UIView+WebCacheOperation.m in Sources */, 537D957617ECC1FE0097C263 /* SDWebImageDecoder.m in Sources */, 537D957717ECC1FE0097C263 /* SDWebImageDownloader.m in Sources */, 537D957817ECC1FE0097C263 /* SDWebImageManager.m in Sources */, diff --git a/SDWebImage/MKAnnotationView+WebCache.m b/SDWebImage/MKAnnotationView+WebCache.m index c4c2f88f..4ceaba85 100644 --- a/SDWebImage/MKAnnotationView+WebCache.m +++ b/SDWebImage/MKAnnotationView+WebCache.m @@ -8,9 +8,9 @@ #import "MKAnnotationView+WebCache.h" #import "objc/runtime.h" +#import "UIView+WebCacheOperation.h" static char imageURLKey; -static char operationKey; @implementation MKAnnotationView (WebCache) @@ -61,17 +61,12 @@ static char operationKey; } }); }]; - objc_setAssociatedObject(self, &operationKey, operation, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + [self setImageLoadOperation:operation forKey:@"MKAnnotationViewImage"]; } } - (void)cancelCurrentImageLoad { - // Cancel in progress downloader from queue - id operation = objc_getAssociatedObject(self, &operationKey); - if (operation) { - [operation cancel]; - objc_setAssociatedObject(self, &operationKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC); - } + [self cancelImageLoadOperationWithKey:@"MKAnnotationViewImage"]; } @end diff --git a/SDWebImage/UIButton+WebCache.h b/SDWebImage/UIButton+WebCache.h index 16205718..cd6316cd 100644 --- a/SDWebImage/UIButton+WebCache.h +++ b/SDWebImage/UIButton+WebCache.h @@ -184,8 +184,13 @@ - (void)setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock; /** - * Cancel the current download + * Cancel the current image download */ -- (void)cancelCurrentImageLoad; +- (void)cancelImageLoadForState:(UIControlState)state; + +/** + * Cancel the current backgroundImage download + */ +- (void)cancelBackgroundImageLoadForState:(UIControlState)state; @end diff --git a/SDWebImage/UIButton+WebCache.m b/SDWebImage/UIButton+WebCache.m index 909c8721..f574af6a 100644 --- a/SDWebImage/UIButton+WebCache.m +++ b/SDWebImage/UIButton+WebCache.m @@ -8,9 +8,9 @@ #import "UIButton+WebCache.h" #import "objc/runtime.h" +#import "UIView+WebCacheOperation.h" static char imageURLStorageKey; -static char operationKey; @implementation UIButton (WebCache) @@ -55,7 +55,7 @@ static char operationKey; - (void)setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock { [self setImage:placeholder forState:state]; - [self cancelCurrentImageLoad]; + [self cancelImageLoadForState:state]; if (!url) { [self.imageURLStorage removeObjectForKey:@(state)]; @@ -79,7 +79,7 @@ static char operationKey; } }); }]; - objc_setAssociatedObject(self, &operationKey, operation, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + [self setImageLoadOperation:operation forState:state]; } - (void)setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state { @@ -103,7 +103,7 @@ static char operationKey; } - (void)setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock { - [self cancelCurrentImageLoad]; + [self cancelImageLoadForState:state]; [self setBackgroundImage:placeholder forState:state]; @@ -122,18 +122,24 @@ static char operationKey; } }); }]; - objc_setAssociatedObject(self, &operationKey, operation, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + [self setBackgroundImageLoadOperation:operation forState:state]; } } +- (void)setImageLoadOperation:(id)operation forState:(UIControlState)state { + [self setImageLoadOperation:operation forKey:[NSString stringWithFormat:@"UIButtonImageOperation%@", @(state)]]; +} -- (void)cancelCurrentImageLoad { - // Cancel in progress downloader from queue - id operation = objc_getAssociatedObject(self, &operationKey); - if (operation) { - [operation cancel]; - objc_setAssociatedObject(self, &operationKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC); - } +- (void)cancelImageLoadForState:(UIControlState)state { + [self cancelImageLoadOperationWithKey:[NSString stringWithFormat:@"UIButtonImageOperation%@", @(state)]]; +} + +- (void)setBackgroundImageLoadOperation:(id)operation forState:(UIControlState)state { + [self setImageLoadOperation:operation forKey:[NSString stringWithFormat:@"UIButtonBackgroundImageOperation%@", @(state)]]; +} + +- (void)cancelBackgroundImageLoadForState:(UIControlState)state { + [self cancelImageLoadOperationWithKey:[NSString stringWithFormat:@"UIButtonBackgroundImageOperation%@", @(state)]]; } - (NSMutableDictionary *)imageURLStorage; diff --git a/SDWebImage/UIImageView+HighlightedWebCache.h b/SDWebImage/UIImageView+HighlightedWebCache.h index c82b8bf7..9e15a1dd 100644 --- a/SDWebImage/UIImageView+HighlightedWebCache.h +++ b/SDWebImage/UIImageView+HighlightedWebCache.h @@ -7,7 +7,8 @@ */ #import -#import "UIImageView+WebCache.h" +#import "SDWebImageCompat.h" +#import "SDWebImageManager.h" /** * Integrates SDWebImage async downloading and caching of remote images with UIImageView for highlighted state. @@ -74,5 +75,9 @@ */ - (void)setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletedBlock)completedBlock; +/** + * Cancel the current download + */ +- (void)cancelCurrentHighlightedImageLoad; @end diff --git a/SDWebImage/UIImageView+HighlightedWebCache.m b/SDWebImage/UIImageView+HighlightedWebCache.m index 1eb817a1..9014be94 100644 --- a/SDWebImage/UIImageView+HighlightedWebCache.m +++ b/SDWebImage/UIImageView+HighlightedWebCache.m @@ -7,9 +7,9 @@ */ #import "UIImageView+HighlightedWebCache.h" -#import "objc/runtime.h" +#import "UIView+WebCacheOperation.h" -static char operationKey; +#define UIImageViewHighlightedWebCacheOperationKey @"highlightedImage" @implementation UIImageView (HighlightedWebCache) @@ -30,7 +30,7 @@ static char operationKey; } - (void)setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletedBlock)completedBlock { - [self cancelCurrentImageLoad]; + [self cancelCurrentHighlightedImageLoad]; if (url) { __weak UIImageView *wself = self; @@ -52,8 +52,12 @@ static char operationKey; } }); }]; - objc_setAssociatedObject(self, &operationKey, operation, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + [self setImageLoadOperation:operation forKey:UIImageViewHighlightedWebCacheOperationKey]; } } +- (void)cancelCurrentHighlightedImageLoad { + [self cancelImageLoadOperationWithKey:UIImageViewHighlightedWebCacheOperationKey]; +} + @end diff --git a/SDWebImage/UIImageView+WebCache.h b/SDWebImage/UIImageView+WebCache.h index 40e2f2cc..c679df69 100644 --- a/SDWebImage/UIImageView+WebCache.h +++ b/SDWebImage/UIImageView+WebCache.h @@ -153,6 +153,6 @@ */ - (void)cancelCurrentImageLoad; -- (void)cancelCurrentArrayLoad; +- (void)cancelCurrentAnimationImagesLoad; @end diff --git a/SDWebImage/UIImageView+WebCache.m b/SDWebImage/UIImageView+WebCache.m index 201e9554..f9d508a6 100644 --- a/SDWebImage/UIImageView+WebCache.m +++ b/SDWebImage/UIImageView+WebCache.m @@ -8,10 +8,9 @@ #import "UIImageView+WebCache.h" #import "objc/runtime.h" +#import "UIView+WebCacheOperation.h" static char imageURLKey; -static char operationKey; -static char operationArrayKey; @implementation UIImageView (WebCache) @@ -68,7 +67,7 @@ static char operationArrayKey; } }); }]; - objc_setAssociatedObject(self, &operationKey, operation, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + [self setImageLoadOperation:operation forKey:@"UIImageViewImageLoad"]; } } @@ -79,7 +78,7 @@ static char operationArrayKey; - (void)setAnimationImagesWithURLs:(NSArray *)arrayOfURLs { - [self cancelCurrentArrayLoad]; + [self cancelCurrentAnimationImagesLoad]; __weak UIImageView *wself = self; NSMutableArray *operationsArray = [[NSMutableArray alloc] init]; @@ -106,27 +105,15 @@ static char operationArrayKey; [operationsArray addObject:operation]; } - objc_setAssociatedObject(self, &operationArrayKey, [NSArray arrayWithArray:operationsArray], OBJC_ASSOCIATION_RETAIN_NONATOMIC); + [self setImageLoadOperation:[NSArray arrayWithArray:operationsArray] forKey:@"UIImageViewAnimationImages"]; } - (void)cancelCurrentImageLoad { - // Cancel in progress downloader from queue - id operation = objc_getAssociatedObject(self, &operationKey); - if (operation) { - [operation cancel]; - objc_setAssociatedObject(self, &operationKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC); - } + [self cancelImageLoadOperationWithKey:@"UIImageViewImageLoad"]; } -- (void)cancelCurrentArrayLoad { - // Cancel in progress downloader from queue - NSArray *operations = objc_getAssociatedObject(self, &operationArrayKey); - for (id operation in operations) { - if (operation) { - [operation cancel]; - } - } - objc_setAssociatedObject(self, &operationArrayKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +- (void)cancelCurrentAnimationImagesLoad { + [self cancelImageLoadOperationWithKey:@"UIImageViewAnimationImages"]; } @end diff --git a/SDWebImage/UIView+WebCacheOperation.h b/SDWebImage/UIView+WebCacheOperation.h new file mode 100644 index 00000000..0e024663 --- /dev/null +++ b/SDWebImage/UIView+WebCacheOperation.h @@ -0,0 +1,20 @@ +// +// UIView+WebCacheOperation.h +// SDWebImage +// +// Created by Whirlwind on 14-5-22. +// Copyright (c) 2014年 Dailymotion. All rights reserved. +// + +#import +#import "SDWebImageManager.h" + +@interface UIView (WebCacheOperation) + +- (void)setImageLoadOperation:(id)operation forKey:(NSString *)Key; + +- (void)cancelImageLoadOperationWithKey:(NSString *)key; + +- (void)removeImageLoadOperationWithKey:(NSString *)key; + +@end diff --git a/SDWebImage/UIView+WebCacheOperation.m b/SDWebImage/UIView+WebCacheOperation.m new file mode 100644 index 00000000..da607359 --- /dev/null +++ b/SDWebImage/UIView+WebCacheOperation.m @@ -0,0 +1,55 @@ +// +// UIView+WebCacheOperation.m +// SDWebImage +// +// Created by Whirlwind on 14-5-22. +// Copyright (c) 2014年 Dailymotion. All rights reserved. +// + +#import "UIView+WebCacheOperation.h" +#import "objc/runtime.h" + +static char loadOperationKey; + +@implementation UIView (WebCacheOperation) + +- (NSMutableDictionary *)operationDictionary { + NSMutableDictionary *operations = objc_getAssociatedObject(self, &loadOperationKey); + if (operations) { + return operations; + } + operations = [NSMutableDictionary dictionary]; + objc_setAssociatedObject(self, &loadOperationKey, operations, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + return operations; +} + +- (void)setImageLoadOperation:(id)operation forKey:(NSString *)key { + [self cancelImageLoadOperationWithKey:key]; + NSMutableDictionary *operationDictionary = [self operationDictionary]; + [operationDictionary setObject:operation forKey:key]; +} + +- (void)cancelImageLoadOperationWithKey:(NSString *)key { + // Cancel in progress downloader from queue + NSMutableDictionary *operationDictionary = [self operationDictionary]; + id operations = [operationDictionary objectForKey:key]; + if (operations) { + if ([operations isKindOfClass:[NSArray class]]) { + for (id operation in operations) { + if (operation) { + [operation cancel]; + } + } + } else { + [(id) operations cancel]; + } + [operationDictionary removeObjectForKey:key]; + } +} + +- (void)removeImageLoadOperationWithKey:(NSString *)key { + NSMutableDictionary *operationDictionary = [self operationDictionary]; + [operationDictionary removeObjectForKey:key]; +} + +@end