From f93cf968327635b61bf0a9fac5cc0de0dcc398ec Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Tue, 8 Nov 2022 16:44:40 +0800 Subject: [PATCH 1/2] Avoid store original disk cache again when using thumbnail or transformer from the full size data This solve #3395 --- SDWebImage/Core/SDWebImageManager.m | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/SDWebImage/Core/SDWebImageManager.m b/SDWebImage/Core/SDWebImageManager.m index 8ffc16ee..6bb7c147 100644 --- a/SDWebImage/Core/SDWebImageManager.m +++ b/SDWebImage/Core/SDWebImageManager.m @@ -565,6 +565,13 @@ static id _defaultImageLoader; } id cacheSerializer = context[SDWebImageContextCacheSerializer]; + // If the original cacheType is disk, since we don't need to store the original data again + // Strip the disk from the originalStoreCacheType + if (cacheType == SDImageCacheTypeDisk) { + if (originalStoreCacheType == SDImageCacheTypeDisk) originalStoreCacheType = SDImageCacheTypeNone; + if (originalStoreCacheType == SDImageCacheTypeAll) originalStoreCacheType = SDImageCacheTypeMemory; + } + // Get original cache key generation without transformer NSString *key = [self originalCacheKeyForURL:url context:context]; if (finished && cacheSerializer && (originalStoreCacheType == SDImageCacheTypeDisk || originalStoreCacheType == SDImageCacheTypeAll)) { From 6a9b578369595eea596abc2f2c5c94dcf5de298a Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Tue, 8 Nov 2022 17:08:34 +0800 Subject: [PATCH 2/2] Added test case `test21ThatQueryOriginalDiskCacheFromThumbnailShouldNotWriteBackDiskCache` --- Tests/Tests/SDWebImageManagerTests.m | 44 ++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/Tests/Tests/SDWebImageManagerTests.m b/Tests/Tests/SDWebImageManagerTests.m index 0dc0c2c6..6097c9d8 100644 --- a/Tests/Tests/SDWebImageManagerTests.m +++ b/Tests/Tests/SDWebImageManagerTests.m @@ -558,6 +558,50 @@ [self waitForExpectationsWithCommonTimeout]; } +- (void)test21ThatQueryOriginalDiskCacheFromThumbnailShouldNotWriteBackDiskCache { + XCTestExpectation *expectation = [self expectationWithDescription:@"Using original disk cache to do thumbnail decoding or transformer, should not save back disk data again"]; + + NSURL *url = [NSURL URLWithString:@"http://via.placeholder.com/503x503.png"]; + NSString *originalKey = url.absoluteString; + // 1. Store the disk data to original cache + CGSize fullSize = CGSizeMake(503, 503); + SDGraphicsImageRenderer *renderer = [[SDGraphicsImageRenderer alloc] initWithSize:fullSize]; + UIImage *fullSizeImage = [renderer imageWithActions:^(CGContextRef _Nonnull context) { + CGContextSetRGBFillColor(context, 1.0, 0.0, 0.0, 1.0); + CGContextSetRGBStrokeColor(context, 1.0, 0.0, 0.0, 1.0); + CGContextFillRect(context, CGRectMake(0, 0, fullSize.width, fullSize.height)); + }]; + NSData *fullSizeData = fullSizeImage.sd_imageData; + [SDImageCache.sharedImageCache storeImageDataToDisk:fullSizeData forKey:originalKey]; + + // 2. Query thumbnail size, should hit full disk cache instead of download + SDWebImageContext *context = @{ + SDWebImageContextImageThumbnailPixelSize: @(CGSizeMake(100, 100)), + SDWebImageContextOriginalQueryCacheType: @(SDImageCacheTypeAll), + SDWebImageContextOriginalStoreCacheType: @(SDImageCacheTypeDisk), + SDWebImageContextQueryCacheType: @(SDImageCacheTypeAll), + SDWebImageContextStoreCacheType: @(SDImageCacheTypeAll) // these 4 are all default values + }; + NSString *key = [SDWebImageManager.sharedManager cacheKeyForURL:url context:context]; // Thumbnail key + [SDImageCache.sharedImageCache removeImageFromDiskForKey:key]; + [SDWebImageManager.sharedManager loadImageWithURL:url options:0 context:context progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) { + expect(cacheType).equal(SDImageCacheTypeDisk); + expect(data).beNil(); // Currently, the thumbnailed and transformed image always data is nil, to avoid confuse user (the image and data represent no longer match) + expect(image.size.width).equal(100); + expect(image.size.height).equal(100); + // 3. Check full size disk cache again, should equal to original stored one + NSData *currentFullSizeData = [SDImageCache.sharedImageCache diskImageDataForKey:originalKey]; + expect(currentFullSizeData).equal(fullSizeData); + // 4. Some extra check that thumbnailed image should store to disk/memory as well to wait for next time query + expect([SDImageCache.sharedImageCache diskImageDataExistsWithKey:key]).beTruthy(); + expect([SDImageCache.sharedImageCache imageFromMemoryCacheForKey:key]).beTruthy(); + + [expectation fulfill]; + }]; + + [self waitForExpectationsWithCommonTimeout]; +} + - (NSString *)testJPEGPath { NSBundle *testBundle = [NSBundle bundleForClass:[self class]]; return [testBundle pathForResource:@"TestImage" ofType:@"jpg"];