From 26d1a95cca0dcdca604173875fb487aa00a568df Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Thu, 23 May 2019 21:36:19 +0800 Subject: [PATCH] Add SDWebImageOptionsProcessor, which can have a global control for both WebCache options and context option for image loading --- SDWebImage.xcodeproj/project.pbxproj | 12 ++++++ SDWebImage/SDWebImageManager.h | 27 ++++++++++++ SDWebImage/SDWebImageManager.m | 26 ++++++++---- SDWebImage/SDWebImageOptionsProcessor.h | 55 +++++++++++++++++++++++++ SDWebImage/SDWebImageOptionsProcessor.m | 52 +++++++++++++++++++++++ WebImage/SDWebImage.h | 1 + 6 files changed, 165 insertions(+), 8 deletions(-) create mode 100644 SDWebImage/SDWebImageOptionsProcessor.h create mode 100644 SDWebImage/SDWebImageOptionsProcessor.m diff --git a/SDWebImage.xcodeproj/project.pbxproj b/SDWebImage.xcodeproj/project.pbxproj index b935e4bd..1f205d11 100644 --- a/SDWebImage.xcodeproj/project.pbxproj +++ b/SDWebImage.xcodeproj/project.pbxproj @@ -37,6 +37,10 @@ 321E60C61F38E91700405457 /* UIImage+ForceDecode.m in Sources */ = {isa = PBXBuildFile; fileRef = 321E60BD1F38E91700405457 /* UIImage+ForceDecode.m */; }; 3237F9E820161AE000A88143 /* NSImage+Compatibility.m in Sources */ = {isa = PBXBuildFile; fileRef = 4397D2F51D0DE2DF00BB2784 /* NSImage+Compatibility.m */; }; 3237F9EB20161AE000A88143 /* NSImage+Compatibility.m in Sources */ = {isa = PBXBuildFile; fileRef = 4397D2F51D0DE2DF00BB2784 /* NSImage+Compatibility.m */; }; + 3244062B2296C5F400A36084 /* SDWebImageOptionsProcessor.h in Headers */ = {isa = PBXBuildFile; fileRef = 324406292296C5F400A36084 /* SDWebImageOptionsProcessor.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3244062C2296C5F400A36084 /* SDWebImageOptionsProcessor.h in Headers */ = {isa = PBXBuildFile; fileRef = 324406292296C5F400A36084 /* SDWebImageOptionsProcessor.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3244062D2296C5F400A36084 /* SDWebImageOptionsProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = 3244062A2296C5F400A36084 /* SDWebImageOptionsProcessor.m */; }; + 3244062E2296C5F400A36084 /* SDWebImageOptionsProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = 3244062A2296C5F400A36084 /* SDWebImageOptionsProcessor.m */; }; 3248475D201775F600AF9E5A /* SDAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 32484757201775F600AF9E5A /* SDAnimatedImageView.m */; }; 3248475F201775F600AF9E5A /* SDAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 32484757201775F600AF9E5A /* SDAnimatedImageView.m */; }; 32484763201775F600AF9E5A /* SDAnimatedImageView+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 32484758201775F600AF9E5A /* SDAnimatedImageView+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -275,6 +279,8 @@ 321E60A11F38E8F600405457 /* SDImageGIFCoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDImageGIFCoder.m; sourceTree = ""; }; 321E60BC1F38E91700405457 /* UIImage+ForceDecode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+ForceDecode.h"; sourceTree = ""; }; 321E60BD1F38E91700405457 /* UIImage+ForceDecode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+ForceDecode.m"; sourceTree = ""; }; + 324406292296C5F400A36084 /* SDWebImageOptionsProcessor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDWebImageOptionsProcessor.h; sourceTree = ""; }; + 3244062A2296C5F400A36084 /* SDWebImageOptionsProcessor.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDWebImageOptionsProcessor.m; sourceTree = ""; }; 32484757201775F600AF9E5A /* SDAnimatedImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDAnimatedImageView.m; sourceTree = ""; }; 32484758201775F600AF9E5A /* SDAnimatedImageView+WebCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SDAnimatedImageView+WebCache.h"; sourceTree = ""; }; 32484759201775F600AF9E5A /* SDAnimatedImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDAnimatedImageView.h; sourceTree = ""; }; @@ -465,6 +471,8 @@ 328BB69B2081FED200760D6C /* SDWebImageCacheKeyFilter.m */, 328BB6A82081FEE500760D6C /* SDWebImageCacheSerializer.h */, 328BB6A92081FEE500760D6C /* SDWebImageCacheSerializer.m */, + 324406292296C5F400A36084 /* SDWebImageOptionsProcessor.h */, + 3244062A2296C5F400A36084 /* SDWebImageOptionsProcessor.m */, ); name = Manager; sourceTree = ""; @@ -728,6 +736,7 @@ 329F1237223FAA3B00B309FD /* SDmetamacros.h in Headers */, 324DF4B6200A14DC008A84CC /* SDWebImageDefine.h in Headers */, 807A122A1F89636300EC2A9B /* SDImageCodersManager.h in Headers */, + 3244062C2296C5F400A36084 /* SDWebImageOptionsProcessor.h in Headers */, 4A2CAE211AB4BB7000B6BC39 /* SDWebImageManager.h in Headers */, 4A2CAE1F1AB4BB6C00B6BC39 /* SDImageCache.h in Headers */, 4A2CAE351AB4BB7500B6BC39 /* UIImageView+WebCache.h in Headers */, @@ -795,6 +804,7 @@ 329F1236223FAA3B00B309FD /* SDmetamacros.h in Headers */, 32484775201775F600AF9E5A /* SDAnimatedImage.h in Headers */, 321E60941F38E8ED00405457 /* SDImageIOCoder.h in Headers */, + 3244062B2296C5F400A36084 /* SDWebImageOptionsProcessor.h in Headers */, 329A18591FFF5DFD008C9A2F /* UIImage+Metadata.h in Headers */, 32D122302080B2EB003685A3 /* SDImageCachesManager.h in Headers */, 5376131A155AD0D5005750A4 /* SDWebImageDownloader.h in Headers */, @@ -963,6 +973,7 @@ 3290FA0C1FA478AF0047D20C /* SDImageFrame.m in Sources */, 325C46232233A02E004CAE11 /* UIColor+HexString.m in Sources */, 321E60C61F38E91700405457 /* UIImage+ForceDecode.m in Sources */, + 3244062E2296C5F400A36084 /* SDWebImageOptionsProcessor.m in Sources */, 328BB6A42081FED200760D6C /* SDWebImageCacheKeyFilter.m in Sources */, 4A2CAE2E1AB4BB7500B6BC39 /* UIImage+GIF.m in Sources */, 80B6DF822142B44400BCB334 /* NSButton+WebCache.m in Sources */, @@ -1025,6 +1036,7 @@ 3290FA0A1FA478AF0047D20C /* SDImageFrame.m in Sources */, 325C46222233A02E004CAE11 /* UIColor+HexString.m in Sources */, 321E60C41F38E91700405457 /* UIImage+ForceDecode.m in Sources */, + 3244062D2296C5F400A36084 /* SDWebImageOptionsProcessor.m in Sources */, 328BB6A22081FED200760D6C /* SDWebImageCacheKeyFilter.m in Sources */, 53761309155AD0D5005750A4 /* SDImageCache.m in Sources */, 80B6DF832142B44500BCB334 /* NSButton+WebCache.m in Sources */, diff --git a/SDWebImage/SDWebImageManager.h b/SDWebImage/SDWebImageManager.h index 5e600916..d1ab013e 100644 --- a/SDWebImage/SDWebImageManager.h +++ b/SDWebImage/SDWebImageManager.h @@ -13,6 +13,7 @@ #import "SDImageTransformer.h" #import "SDWebImageCacheKeyFilter.h" #import "SDWebImageCacheSerializer.h" +#import "SDWebImageOptionsProcessor.h" typedef void(^SDExternalCompletionBlock)(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL); @@ -153,6 +154,32 @@ SDWebImageManager *manager = [SDWebImageManager sharedManager]; */ @property (nonatomic, strong, nullable) id cacheSerializer; +/** + The options processor is used, to have a global control for all the image request options and context option for current manager. + @note If you use `transformer`, `cacheKeyFilter` or `cacheSerializer` property of manager, the input context option already apply those properties before passed. This options processor is a better replacement for those property in common usage. + For example, you can control the global options, based on the URL or original context option like the below code. + + @code + SDWebImageManager.sharedManager.optionsProcessor = [SDWebImageOptionsProcessor optionsProcessorWithBlock:^SDWebImageOptionsResult * _Nullable(NSURL * _Nullable url, SDWebImageOptions options, SDWebImageContext * _Nullable context) { + // Only do animation on `SDAnimatedImageView` + if (!context[SDWebImageContextAnimatedImageClass]) { + options |= SDWebImageDecodeFirstFrameOnly; + } + // Do not force decode for png url + if ([url.lastPathComponent isEqualToString:@"png"]) { + options |= SDWebImageAvoidDecodeImage; + } + // Always use screen scale factor + SDWebImageMutableContext *mutableContext = [NSDictionary dictionaryWithDictionary:context]; + mutableContext[SDWebImageContextImageScaleFactor] = @(UIScreen.mainScreen.scale); + context = [mutableContext copy]; + + return [[SDWebImageOptionsResult alloc] initWithOptions:options context:context]; + }]; + @endcode + */ +@property (nonatomic, strong, nullable) id optionsProcessor; + /** * Check one or more operations running */ diff --git a/SDWebImage/SDWebImageManager.m b/SDWebImage/SDWebImageManager.m index 622eef1c..00ec0601 100644 --- a/SDWebImage/SDWebImageManager.m +++ b/SDWebImage/SDWebImageManager.m @@ -151,11 +151,11 @@ static id _defaultImageLoader; [self.runningOperations addObject:operation]; SD_UNLOCK(self.runningOperationsLock); - // Preprocess the context arg to provide the default value from manager - context = [self processedContextWithContext:context]; + // Preprocess the options and context arg to decide the final the result for manager + SDWebImageOptionsResult *result = [self processedResultForURL:url options:options context:context]; // Start the entry to load image from cache - [self callCacheProcessForOperation:operation url:url options:options context:context progress:progressBlock completed:completedBlock]; + [self callCacheProcessForOperation:operation url:url options:result.options context:result.context progress:progressBlock completed:completedBlock]; return operation; } @@ -381,7 +381,8 @@ static id _defaultImageLoader; return shouldBlockFailedURL; } -- (SDWebImageContext *)processedContextWithContext:(SDWebImageContext *)context { +- (SDWebImageOptionsResult *)processedResultForURL:(NSURL *)url options:(SDWebImageOptions)options context:(SDWebImageContext *)context { + SDWebImageOptionsResult *result; SDWebImageMutableContext *mutableContext = [SDWebImageMutableContext dictionary]; // Image Transformer from manager @@ -400,12 +401,21 @@ static id _defaultImageLoader; [mutableContext setValue:cacheSerializer forKey:SDWebImageContextCacheSerializer]; } - if (mutableContext.count == 0) { - return context; - } else { + if (mutableContext.count > 0) { [mutableContext addEntriesFromDictionary:context]; - return [mutableContext copy]; + context = [mutableContext copy]; } + + // Apply options processor + if (self.optionsProcessor) { + result = [self.optionsProcessor processedResultForURL:url options:options context:context]; + } + if (!result) { + // Use default options result + result = [[SDWebImageOptionsResult alloc] initWithOptions:options context:context]; + } + + return result; } @end diff --git a/SDWebImage/SDWebImageOptionsProcessor.h b/SDWebImage/SDWebImageOptionsProcessor.h new file mode 100644 index 00000000..ab4bc4f1 --- /dev/null +++ b/SDWebImage/SDWebImageOptionsProcessor.h @@ -0,0 +1,55 @@ +/* + * 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 +#import "SDWebImageCompat.h" +#import "SDWebImageDefine.h" + +@class SDWebImageOptionsResult; + +typedef SDWebImageOptionsResult * _Nullable(^SDWebImageOptionsProcessorBlock)(NSURL * _Nullable url, SDWebImageOptions options, SDWebImageContext * _Nullable context); + +/** + The options result contains both options and context. + */ +@interface SDWebImageOptionsResult : NSObject + +@property (nonatomic, assign) SDWebImageOptions options; +@property (nonatomic, copy, nullable) SDWebImageContext *context; + +- (nonnull instancetype)initWithOptions:(SDWebImageOptions)options context:(nullable SDWebImageContext *)context; + +@end + +/** + This is the protocol for options processor. + Options processor can be used, to control the final result for individual image request's `SDWebImageOptions` and `SDWebImageContext` + Implements the protocol to have a global control for each indivadual image request's option. + */ +@protocol SDWebImageOptionsProcessor + +/** + Return the processed options result for specify image URL, with its options and context + + @param url The URL to the image + @param options A mask to specify options to use for this request + @param context A context contains different options to perform specify changes or processes, see `SDWebImageContextOption`. This hold the extra objects which `options` enum can not hold. + @return The processed result, contains both options and context + */ +- (nullable SDWebImageOptionsResult *)processedResultForURL:(nullable NSURL *)url + options:(SDWebImageOptions)options + context:(nullable SDWebImageContext *)context; + +@end + +@interface SDWebImageOptionsProcessor : NSObject + +- (nonnull instancetype)initWithBlock:(nonnull SDWebImageOptionsProcessorBlock)block; ++ (nonnull instancetype)optionsProcessorWithBlock:(nonnull SDWebImageOptionsProcessorBlock)block; + +@end diff --git a/SDWebImage/SDWebImageOptionsProcessor.m b/SDWebImage/SDWebImageOptionsProcessor.m new file mode 100644 index 00000000..23cb162d --- /dev/null +++ b/SDWebImage/SDWebImageOptionsProcessor.m @@ -0,0 +1,52 @@ +/* + * 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 "SDWebImageOptionsProcessor.h" + +@implementation SDWebImageOptionsResult + +- (instancetype)initWithOptions:(SDWebImageOptions)options context:(SDWebImageContext *)context { + self = [super init]; + if (self) { + self.options = options; + self.context = context; + } + return self; +} + +@end + +@interface SDWebImageOptionsProcessor () + +@property (nonatomic, copy, nonnull) SDWebImageOptionsProcessorBlock block; + +@end + +@implementation SDWebImageOptionsProcessor + +- (instancetype)initWithBlock:(SDWebImageOptionsProcessorBlock)block { + self = [super init]; + if (self) { + self.block = block; + } + return self; +} + ++ (instancetype)optionsProcessorWithBlock:(SDWebImageOptionsProcessorBlock)block { + SDWebImageOptionsProcessor *optionsProcessor = [[SDWebImageOptionsProcessor alloc] initWithBlock:block]; + return optionsProcessor; +} + +- (SDWebImageOptionsResult *)processedResultForURL:(NSURL *)url options:(SDWebImageOptions)options context:(SDWebImageContext *)context { + if (!self.block) { + return nil; + } + return self.block(url, options, context); +} + +@end diff --git a/WebImage/SDWebImage.h b/WebImage/SDWebImage.h index b09d2d1d..89c2ec36 100644 --- a/WebImage/SDWebImage.h +++ b/WebImage/SDWebImage.h @@ -66,6 +66,7 @@ FOUNDATION_EXPORT const unsigned char WebImageVersionString[]; #import #import #import +#import // Mac #if __has_include()