Skip to content

Commit f3a1d91

Browse files
authored
Merge pull request SDWebImage#3788 from dreampiggy/bugfix/cache_query_type_optimization
Fix the issue that previous optimization for special case (multiple same URL in prefetcher list) breaks the `queryCacheType` option sematic
2 parents 15f6675 + 3257ea2 commit f3a1d91

File tree

5 files changed

+28
-13
lines changed

5 files changed

+28
-13
lines changed

.github/workflows/CI.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,12 @@ jobs:
4545
DEVELOPER_DIR: /Applications/Xcode_16.0.app
4646
WORKSPACE_NAME: SDWebImage.xcworkspace
4747
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
48-
iosDestination: platform=iOS Simulator,name=iPhone 16 Pro
48+
iosDestination: generic/platform=iOS Simulator
4949
macOSDestination: platform=macOS,arch=x86_64
5050
macCatalystDestination: platform=macOS,arch=x86_64,variant=Mac Catalyst
51-
tvOSDestination: platform=tvOS Simulator,name=Apple TV 4K (3rd generation)
52-
watchOSDestination: platform=watchOS Simulator,name=Apple Watch Ultra 2 (49mm)
53-
visionOSDestination: platform=visionOS Simulator,name=Apple Vision Pro
51+
tvOSDestination: generic/platform=tvOS Simulator
52+
watchOSDestination: generic/platform=watchOS Simulator
53+
visionOSDestination: generic/platform=visionOS Simulator
5454
steps:
5555
- name: Checkout
5656
uses: actions/checkout@v3
@@ -106,7 +106,7 @@ jobs:
106106
platform: [iOS, macOS, tvOS, visionOS]
107107
include:
108108
- platform: iOS
109-
destination: platform=iOS Simulator,name=iPhone 16 Pro
109+
destination: platform=iOS Simulator,name=iPhone 16 Pro Max
110110
scheme: iOS
111111
flag: ios
112112
- platform: macOS

SDWebImage/Core/SDImageCache.m

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -619,7 +619,8 @@ - (nullable SDImageCacheToken *)queryCacheOperationForKey:(nullable NSString *)k
619619

620620
// First check the in-memory cache...
621621
UIImage *image;
622-
if (queryCacheType != SDImageCacheTypeDisk) {
622+
BOOL shouldQueryDiskOnly = (queryCacheType == SDImageCacheTypeDisk);
623+
if (!shouldQueryDiskOnly) {
623624
image = [self imageFromMemoryCacheForKey:key];
624625
}
625626

@@ -683,14 +684,19 @@ - (nullable SDImageCacheToken *)queryCacheOperationForKey:(nullable NSString *)k
683684
// the image is from in-memory cache, but need image data
684685
diskImage = image;
685686
} else if (diskData) {
687+
// the image memory cache miss, need image data and image
686688
BOOL shouldCacheToMemory = YES;
687689
if (context[SDWebImageContextStoreCacheType]) {
688690
SDImageCacheType cacheType = [context[SDWebImageContextStoreCacheType] integerValue];
689691
shouldCacheToMemory = (cacheType == SDImageCacheTypeAll || cacheType == SDImageCacheTypeMemory);
690692
}
691-
// Special case: If user query image in list for the same URL, to avoid decode and write **same** image object into disk cache multiple times, we query and check memory cache here again.
692-
if (shouldCacheToMemory && self.config.shouldCacheImagesInMemory) {
693-
diskImage = [self.memoryCache objectForKey:key];
693+
// Special case: If user query image in list for the same URL, to avoid decode and write **same** image object into disk cache multiple times, we query and check memory cache here again. See: #3523
694+
// This because disk operation can be async, previous sync check of `memory cache miss`, does not gurantee current check of `memory cache miss`
695+
if (!shouldQueryDiskSync) {
696+
// First check the in-memory cache...
697+
if (!shouldQueryDiskOnly) {
698+
diskImage = [self imageFromMemoryCacheForKey:key];
699+
}
694700
}
695701
// decode image data only if in-memory cache missed
696702
if (!diskImage) {

Tests/Tests/SDAnimatedImageTest.m

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -313,14 +313,17 @@ - (void)test21AnimatedImageViewSetProgressiveAnimatedImage {
313313
- (void)test22AnimatedImageViewCategory {
314314
XCTestExpectation *expectation = [self expectationWithDescription:@"test SDAnimatedImageView view category"];
315315
SDAnimatedImageView *imageView = [SDAnimatedImageView new];
316-
NSURL *testURL = [NSURL URLWithString:kTestGIFURL];
317-
[imageView sd_setImageWithURL:testURL completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
316+
NSURL *testURL = [NSURL URLWithString:@"https://media.giphy.com/media/3oeji6siihbdrxxi40/giphy.gif"];
317+
[SDImageCache.sharedImageCache removeImageFromMemoryForKey:testURL.absoluteString];
318+
[SDImageCache.sharedImageCache removeImageFromDiskForKey:testURL.absoluteString];
319+
// I don't know why, but `fromLoaderOnly` is need for iOS Unit Test on GitHub Action
320+
[imageView sd_setImageWithURL:testURL placeholderImage:nil options:SDWebImageFromLoaderOnly completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
318321
expect(error).to.beNil();
319322
expect(image).notTo.beNil();
320323
expect([image isKindOfClass:[SDAnimatedImage class]]).beTruthy();
321324
[expectation fulfill];
322325
}];
323-
[self waitForExpectationsWithCommonTimeout];
326+
[self waitForExpectationsWithTimeout:kAsyncTestTimeout * 2 handler:nil];
324327
}
325328

326329
- (void)test23AnimatedImageViewCategoryProgressive {

Tests/Tests/SDTestCase.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
NSString *const kTestJPEGURL = @"https://placehold.co/50x50.jpg";
1515
NSString *const kTestProgressiveJPEGURL = @"https://raw.githubusercontent.com/ibireme/YYImage/master/Demo/YYImageDemo/mew_progressive.jpg";
1616
NSString *const kTestPNGURL = @"https://placehold.co/50x50.png";
17-
NSString *const kTestGIFURL = @"https://upload.wikimedia.org/wikipedia/commons/2/2c/Rotating_earth_%28large%29.gif";
17+
NSString *const kTestGIFURL = @"https://upload.wikimedia.org/wikipedia/commons/3/31/Eokxd.gif";
1818
NSString *const kTestAPNGPURL = @"https://upload.wikimedia.org/wikipedia/commons/1/14/Animated_PNG_example_bouncing_beach_ball.png";
1919

2020
@implementation SDTestCase

Tests/Tests/SDWebImageManagerTests.m

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,16 +377,22 @@ - (void)test15ThatQueryCacheTypeWork {
377377
NSURL *url = [NSURL URLWithString:@"https://placehold.co/101x101.png"];
378378
NSString *key = [SDWebImageManager.sharedManager cacheKeyForURL:url];
379379
NSData *testImageData = [NSData dataWithContentsOfFile:[self testJPEGPath]];
380+
UIImage *testImage = [UIImage sd_imageWithData:testImageData];
380381
[SDImageCache.sharedImageCache storeImageDataToDisk:testImageData forKey:key];
381382

382383
// Query memory first
383384
[SDWebImageManager.sharedManager loadImageWithURL:url options:SDWebImageFromCacheOnly context:@{SDWebImageContextQueryCacheType : @(SDImageCacheTypeMemory)} progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
384385
expect(image).beNil();
385386
expect(cacheType).equal(SDImageCacheTypeNone);
387+
// Store the image to memory
388+
[SDImageCache.sharedImageCache storeImageToMemory:testImage forKey:key];
386389
// Query disk secondly
387390
[SDWebImageManager.sharedManager loadImageWithURL:url options:SDWebImageFromCacheOnly context:@{SDWebImageContextQueryCacheType : @(SDImageCacheTypeDisk)} progress:nil completed:^(UIImage * _Nullable image2, NSData * _Nullable data2, NSError * _Nullable error2, SDImageCacheType cacheType2, BOOL finished2, NSURL * _Nullable imageURL2) {
388391
expect(image2).notTo.beNil();
389392
expect(cacheType2).equal(SDImageCacheTypeDisk);
393+
// We should ensure that this disk image is not the same one in-memory
394+
expect(image2 != testImage).beTruthy();
395+
[SDImageCache.sharedImageCache removeImageFromMemoryForKey:key];
390396
[SDImageCache.sharedImageCache removeImageFromDiskForKey:key];
391397
[expectation fulfill];
392398
}];

0 commit comments

Comments
 (0)