Authored by DreamPiggy
Committed by GitHub

Merge pull request #2245 from dreampiggy/feature_cache_serializer

Add cacheKeyFilter to allow user provide modified version of data when storing the disk cache in SDWebImageManager
@@ -122,7 +122,9 @@ typedef void(^SDExternalCompletionBlock)(UIImage * _Nullable image, NSError * _N @@ -122,7 +122,9 @@ typedef void(^SDExternalCompletionBlock)(UIImage * _Nullable image, NSError * _N
122 122
123 typedef void(^SDInternalCompletionBlock)(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL); 123 typedef void(^SDInternalCompletionBlock)(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL);
124 124
125 -typedef NSString * _Nullable (^SDWebImageCacheKeyFilterBlock)(NSURL * _Nullable url); 125 +typedef NSString * _Nullable(^SDWebImageCacheKeyFilterBlock)(NSURL * _Nullable url);
  126 +
  127 +typedef NSData * _Nullable(^SDWebImageCacheSerializerBlock)(UIImage * _Nonnull image, NSData * _Nullable data, NSURL * _Nullable imageURL);
126 128
127 129
128 @class SDWebImageManager; 130 @class SDWebImageManager;
@@ -203,16 +205,36 @@ SDWebImageManager *manager = [SDWebImageManager sharedManager]; @@ -203,16 +205,36 @@ SDWebImageManager *manager = [SDWebImageManager sharedManager];
203 * 205 *
204 * @code 206 * @code
205 207
206 -[[SDWebImageManager sharedManager] setCacheKeyFilter:^(NSURL *url) { 208 +SDWebImageManager.sharedManager.cacheKeyFilter = ^(NSURL * _Nullable url) {
207 url = [[NSURL alloc] initWithScheme:url.scheme host:url.host path:url.path]; 209 url = [[NSURL alloc] initWithScheme:url.scheme host:url.host path:url.path];
208 return [url absoluteString]; 210 return [url absoluteString];
209 -}]; 211 +};
210 212
211 * @endcode 213 * @endcode
212 */ 214 */
213 @property (nonatomic, copy, nullable) SDWebImageCacheKeyFilterBlock cacheKeyFilter; 215 @property (nonatomic, copy, nullable) SDWebImageCacheKeyFilterBlock cacheKeyFilter;
214 216
215 /** 217 /**
  218 + * The cache serializer is a block used to convert the decoded image, the source downloaded data, to the actual data used for storing to the disk cache. If you return nil, means to generate the data from the image instance, see `SDImageCache`.
  219 + * For example, if you are using WebP images and facing the slow decoding time issue when later retriving from disk cache again. You can try to encode the decoded image to JPEG/PNG format to disk cache instead of source downloaded data.
  220 + * @note The `image` arg is nonnull, but when you also provide a image transformer and the image is transformed, the `data` arg may be nil, take attention to this case.
  221 + * @note This method is called from a global queue in order to not to block the main thread.
  222 + * @code
  223 + SDWebImageManager.sharedManager.cacheKeyFilter = ^NSData * _Nullable(UIImage * _Nonnull image, NSData * _Nullable data, NSURL * _Nullable imageURL) {
  224 + SDImageFormat format = [NSData sd_imageFormatForImageData:data];
  225 + switch (format) {
  226 + case SDImageFormatWebP:
  227 + return image.images ? data : nil;
  228 + default:
  229 + return data;
  230 + }
  231 + };
  232 + * @endcode
  233 + * The default value is nil. Means we just store the source downloaded data to disk cache.
  234 + */
  235 +@property (nonatomic, copy, nullable) SDWebImageCacheSerializerBlock cacheSerializer;
  236 +
  237 +/**
216 * Returns global SDWebImageManager instance. 238 * Returns global SDWebImageManager instance.
217 * 239 *
218 * @return SDWebImageManager shared instance 240 * @return SDWebImageManager shared instance
@@ -239,16 +239,29 @@ @@ -239,16 +239,29 @@
239 239
240 if (transformedImage && finished) { 240 if (transformedImage && finished) {
241 BOOL imageWasTransformed = ![transformedImage isEqual:downloadedImage]; 241 BOOL imageWasTransformed = ![transformedImage isEqual:downloadedImage];
  242 + NSData *cacheData;
242 // pass nil if the image was transformed, so we can recalculate the data from the image 243 // pass nil if the image was transformed, so we can recalculate the data from the image
243 - [self.imageCache storeImage:transformedImage imageData:(imageWasTransformed ? nil : downloadedData) forKey:key toDisk:cacheOnDisk completion:nil]; 244 + if (self.cacheSerializer) {
  245 + cacheData = self.cacheSerializer(transformedImage, (imageWasTransformed ? nil : downloadedData), url);
  246 + } else {
  247 + cacheData = (imageWasTransformed ? nil : downloadedData);
  248 + }
  249 + [self.imageCache storeImage:transformedImage imageData:cacheData forKey:key toDisk:cacheOnDisk completion:nil];
244 } 250 }
245 251
246 [self callCompletionBlockForOperation:strongSubOperation completion:completedBlock image:transformedImage data:downloadedData error:nil cacheType:SDImageCacheTypeNone finished:finished url:url]; 252 [self callCompletionBlockForOperation:strongSubOperation completion:completedBlock image:transformedImage data:downloadedData error:nil cacheType:SDImageCacheTypeNone finished:finished url:url];
247 }); 253 });
248 } else { 254 } else {
249 if (downloadedImage && finished) { 255 if (downloadedImage && finished) {
  256 + if (self.cacheSerializer) {
  257 + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
  258 + NSData *cacheData = self.cacheSerializer(downloadedImage, downloadedData, url);
  259 + [self.imageCache storeImage:downloadedImage imageData:cacheData forKey:key toDisk:cacheOnDisk completion:nil];
  260 + });
  261 + } else {
250 [self.imageCache storeImage:downloadedImage imageData:downloadedData forKey:key toDisk:cacheOnDisk completion:nil]; 262 [self.imageCache storeImage:downloadedImage imageData:downloadedData forKey:key toDisk:cacheOnDisk completion:nil];
251 } 263 }
  264 + }
252 [self callCompletionBlockForOperation:strongSubOperation completion:completedBlock image:downloadedImage data:downloadedData error:nil cacheType:SDImageCacheTypeNone finished:finished url:url]; 265 [self callCompletionBlockForOperation:strongSubOperation completion:completedBlock image:downloadedImage data:downloadedData error:nil cacheType:SDImageCacheTypeNone finished:finished url:url];
253 } 266 }
254 } 267 }