diff --git a/SDWebImage/Core/SDWebImageDefine.h b/SDWebImage/Core/SDWebImageDefine.h index 96f71d68..40808047 100644 --- a/SDWebImage/Core/SDWebImageDefine.h +++ b/SDWebImage/Core/SDWebImageDefine.h @@ -272,6 +272,13 @@ FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextQueryC */ FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextStoreCacheType; + +/** + The same behavior like `SDWebImageContextQueryCacheType`, but control the query cache type for the original image when you use image transformer feature. This allows the detail control of cache query for these two images. For example, if you want to query the transformed image from both memory/disk cache, query the original image from disk cache only, use `[.queryCacheType : .all, .originalQueryCacheType : .disk]` + If not provide or the value is invalid, we will use `SDImageCacheTypeNone`, which does not query the original image from cache. (NSNumber) + */ +FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextOriginalQueryCacheType; + /** The same behavior like `SDWebImageContextStoreCacheType`, but control the store cache type for the original image when you use image transformer feature. This allows the detail control of cache storage for these two images. For example, if you want to store the transformed image into both memory/disk cache, store the original image into disk cache only, use `[.storeCacheType : .all, .originalStoreCacheType : .disk]` If not provide or the value is invalid, we will use `SDImageCacheTypeNone`, which does not store the original image into cache. (NSNumber) diff --git a/SDWebImage/Core/SDWebImageDefine.m b/SDWebImage/Core/SDWebImageDefine.m index 2809af69..4c58061d 100644 --- a/SDWebImage/Core/SDWebImageDefine.m +++ b/SDWebImage/Core/SDWebImageDefine.m @@ -129,6 +129,7 @@ SDWebImageContextOption const SDWebImageContextImagePreserveAspectRatio = @"imag SDWebImageContextOption const SDWebImageContextImageThumbnailPixelSize = @"imageThumbnailPixelSize"; SDWebImageContextOption const SDWebImageContextQueryCacheType = @"queryCacheType"; SDWebImageContextOption const SDWebImageContextStoreCacheType = @"storeCacheType"; +SDWebImageContextOption const SDWebImageContextOriginalQueryCacheType = @"originalQueryCacheType"; SDWebImageContextOption const SDWebImageContextOriginalStoreCacheType = @"originalStoreCacheType"; SDWebImageContextOption const SDWebImageContextAnimatedImageClass = @"animatedImageClass"; SDWebImageContextOption const SDWebImageContextDownloadRequestModifier = @"downloadRequestModifier"; diff --git a/SDWebImage/Core/SDWebImageManager.m b/SDWebImage/Core/SDWebImageManager.m index 2adf2b64..4f615911 100644 --- a/SDWebImage/Core/SDWebImageManager.m +++ b/SDWebImage/Core/SDWebImageManager.m @@ -228,7 +228,7 @@ static id _defaultImageLoader; #pragma mark - Private -// Query cache process +// Query normal cache process - (void)callCacheProcessForOperation:(nonnull SDWebImageCombinedOperation *)operation url:(nonnull NSURL *)url options:(SDWebImageOptions)options @@ -242,13 +242,15 @@ static id _defaultImageLoader; } else { imageCache = self.imageCache; } - // Check whether we should query cache - BOOL shouldQueryCache = !SD_OPTIONS_CONTAINS(options, SDWebImageFromLoaderOnly); + // Get the query cache type SDImageCacheType queryCacheType = SDImageCacheTypeAll; if (context[SDWebImageContextQueryCacheType]) { queryCacheType = [context[SDWebImageContextQueryCacheType] integerValue]; } + + // Check whether we should query cache + BOOL shouldQueryCache = !SD_OPTIONS_CONTAINS(options, SDWebImageFromLoaderOnly); if (shouldQueryCache) { NSString *key = [self cacheKeyForURL:url context:context]; @weakify(operation); @@ -260,6 +262,12 @@ static id _defaultImageLoader; [self safelyRemoveOperationFromRunning:operation]; return; } + else if (context[SDWebImageContextImageTransformer] && !cachedImage) { + // Have a chance to quary original cache instead of downloading + [self callOriginalCacheProcessForOperation:operation url:url options:options context:context progress:progressBlock completed:completedBlock]; + return ; + } + // Continue download process [self callDownloadProcessForOperation:operation url:url options:options context:context cachedImage:cachedImage cachedData:cachedData cacheType:cacheType progress:progressBlock completed:completedBlock]; }]; @@ -269,6 +277,70 @@ static id _defaultImageLoader; } } +// Query original cache process +- (void)callOriginalCacheProcessForOperation:(nonnull SDWebImageCombinedOperation *)operation + url:(nonnull NSURL *)url + options:(SDWebImageOptions)options + context:(nullable SDWebImageContext *)context + progress:(nullable SDImageLoaderProgressBlock)progressBlock + completed:(nullable SDInternalCompletionBlock)completedBlock { + // Grab the image cache to use + id imageCache; + if ([context[SDWebImageContextImageCache] conformsToProtocol:@protocol(SDImageCache)]) { + imageCache = context[SDWebImageContextImageCache]; + } else { + imageCache = self.imageCache; + } + + // Get the original query cache type + SDImageCacheType originalQueryCacheType = SDImageCacheTypeNone; + if (context[SDWebImageContextOriginalQueryCacheType]) { + originalQueryCacheType = [context[SDWebImageContextOriginalQueryCacheType] integerValue]; + } + + // Check whether we should query original cache + BOOL shouldQueryOriginalCache = (originalQueryCacheType != SDImageCacheTypeNone); + if (shouldQueryOriginalCache) { + // Change originContext to mutable + SDWebImageMutableContext * __block originContext; + if (context) { + originContext = [context mutableCopy]; + } else { + originContext = [NSMutableDictionary dictionary]; + } + + // Disable transformer for cache key generation + id transformer = originContext[SDWebImageContextImageTransformer]; + originContext[SDWebImageContextImageTransformer] = [NSNull null]; + + NSString *key = [self cacheKeyForURL:url context:originContext]; + @weakify(operation); + operation.cacheOperation = [imageCache queryImageForKey:key options:options context:context cacheType:originalQueryCacheType completion:^(UIImage * _Nullable cachedImage, NSData * _Nullable cachedData, SDImageCacheType cacheType) { + @strongify(operation); + if (!operation || operation.isCancelled) { + // Image combined operation cancelled by user + [self callCompletionBlockForOperation:operation completion:completedBlock error:[NSError errorWithDomain:SDWebImageErrorDomain code:SDWebImageErrorCancelled userInfo:@{NSLocalizedDescriptionKey : @"Operation cancelled by user during querying the cache"}] url:url]; + [self safelyRemoveOperationFromRunning:operation]; + return; + } + + // Add original transformer + if (transformer) { + originContext[SDWebImageContextImageTransformer] = transformer; + } + + // Use the store cache process instead of downloading, and ignore .refreshCached option for now + [self callStoreCacheProcessForOperation:operation url:url options:options context:context downloadedImage:cachedImage downloadedData:cachedData finished:YES progress:progressBlock completed:completedBlock]; + + [self safelyRemoveOperationFromRunning:operation]; + }]; + } + else { + // Continue download process + [self callDownloadProcessForOperation:operation url:url options:options context:context cachedImage:nil cachedData:nil cacheType:originalQueryCacheType progress:progressBlock completed:completedBlock]; + } +} + // Download process - (void)callDownloadProcessForOperation:(nonnull SDWebImageCombinedOperation *)operation url:(nonnull NSURL *)url @@ -286,6 +358,7 @@ static id _defaultImageLoader; } else { imageLoader = self.imageLoader; } + // Check whether we should download image from network BOOL shouldDownload = !SD_OPTIONS_CONTAINS(options, SDWebImageFromCacheOnly); shouldDownload &= (!cachedImage || options & SDWebImageRefreshCached);