Merge pull request #2968 from dreampiggy/feature_query_cache_type
Added new query cache type support, including the SDImageCache API and context option
This commit is contained in:
commit
51dee05acf
|
@ -235,6 +235,15 @@ typedef NS_OPTIONS(NSUInteger, SDImageCacheOptions) {
|
|||
*/
|
||||
- (nullable NSData *)diskImageDataForKey:(nullable NSString *)key;
|
||||
|
||||
/**
|
||||
* Asynchronously load the image data in disk cache. You can decode the image data to image after loaded.
|
||||
*
|
||||
* @param key The unique key used to store the wanted image
|
||||
* @param completionBlock the block to be executed when the check is done.
|
||||
* @note the completion block will be always executed on the main queue
|
||||
*/
|
||||
- (void)diskImageDataQueryForKey:(nullable NSString *)key completion:(nullable SDImageCacheQueryDataCompletionBlock)completionBlock;
|
||||
|
||||
/**
|
||||
* Operation that queries the cache asynchronously and call the completion when done.
|
||||
*
|
||||
|
@ -268,6 +277,19 @@ typedef NS_OPTIONS(NSUInteger, SDImageCacheOptions) {
|
|||
*/
|
||||
- (nullable NSOperation *)queryCacheOperationForKey:(nullable NSString *)key options:(SDImageCacheOptions)options context:(nullable SDWebImageContext *)context done:(nullable SDImageCacheQueryCompletionBlock)doneBlock;
|
||||
|
||||
/**
|
||||
* Asynchronously queries the cache with operation and call the completion when done.
|
||||
*
|
||||
* @param key The unique key used to store the wanted image. If you want transformed or thumbnail image, calculate the key with `SDTransformedKeyForKey`, `SDThumbnailedKeyForKey`, or generate the cache key from url with `cacheKeyForURL:context:`.
|
||||
* @param options A mask to specify options to use for this cache query
|
||||
* @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.
|
||||
* @param queryCacheType Specify where to query the cache from. By default we use `.all`, which means both memory cache and disk cache. You can choose to query memory only or disk only as well. Pass `.none` is invalid and callback with nil immediatelly.
|
||||
* @param doneBlock The completion block. Will not get called if the operation is cancelled
|
||||
*
|
||||
* @return a NSOperation instance containing the cache op
|
||||
*/
|
||||
- (nullable NSOperation *)queryCacheOperationForKey:(nullable NSString *)key options:(SDImageCacheOptions)options context:(nullable SDWebImageContext *)context cacheType:(SDImageCacheType)queryCacheType done:(nullable SDImageCacheQueryCompletionBlock)doneBlock;
|
||||
|
||||
/**
|
||||
* Synchronously query the memory cache.
|
||||
*
|
||||
|
|
|
@ -314,6 +314,17 @@
|
|||
return [self.diskCache containsDataForKey:key];
|
||||
}
|
||||
|
||||
- (void)diskImageDataQueryForKey:(NSString *)key completion:(SDImageCacheQueryDataCompletionBlock)completionBlock {
|
||||
dispatch_async(self.ioQueue, ^{
|
||||
NSData *imageData = [self diskImageDataBySearchingAllPathsForKey:key];
|
||||
if (completionBlock) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
completionBlock(imageData);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (nullable NSData *)diskImageDataForKey:(nullable NSString *)key {
|
||||
if (!key) {
|
||||
return nil;
|
||||
|
@ -426,12 +437,23 @@
|
|||
}
|
||||
|
||||
- (nullable NSOperation *)queryCacheOperationForKey:(nullable NSString *)key options:(SDImageCacheOptions)options context:(nullable SDWebImageContext *)context done:(nullable SDImageCacheQueryCompletionBlock)doneBlock {
|
||||
return [self queryCacheOperationForKey:key options:options context:context cacheType:SDImageCacheTypeAll done:doneBlock];
|
||||
}
|
||||
|
||||
- (nullable NSOperation *)queryCacheOperationForKey:(nullable NSString *)key options:(SDImageCacheOptions)options context:(nullable SDWebImageContext *)context cacheType:(SDImageCacheType)queryCacheType done:(nullable SDImageCacheQueryCompletionBlock)doneBlock {
|
||||
if (!key) {
|
||||
if (doneBlock) {
|
||||
doneBlock(nil, nil, SDImageCacheTypeNone);
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
// Invalid cache type
|
||||
if (queryCacheType == SDImageCacheTypeNone) {
|
||||
if (doneBlock) {
|
||||
doneBlock(nil, nil, SDImageCacheTypeNone);
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
id<SDImageTransformer> transformer = context[SDWebImageContextImageTransformer];
|
||||
if (transformer) {
|
||||
|
@ -441,7 +463,10 @@
|
|||
}
|
||||
|
||||
// First check the in-memory cache...
|
||||
UIImage *image = [self imageFromMemoryCacheForKey:key];
|
||||
UIImage *image;
|
||||
if (queryCacheType != SDImageCacheTypeDisk) {
|
||||
image = [self imageFromMemoryCacheForKey:key];
|
||||
}
|
||||
|
||||
if (image) {
|
||||
if (options & SDImageCacheDecodeFirstFrameOnly) {
|
||||
|
@ -464,7 +489,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
BOOL shouldQueryMemoryOnly = (image && !(options & SDImageCacheQueryMemoryData));
|
||||
BOOL shouldQueryMemoryOnly = (queryCacheType == SDImageCacheTypeMemory) || (image && !(options & SDImageCacheQueryMemoryData));
|
||||
if (shouldQueryMemoryOnly) {
|
||||
if (doneBlock) {
|
||||
doneBlock(image, nil, SDImageCacheTypeMemory);
|
||||
|
@ -699,6 +724,10 @@
|
|||
#pragma mark - SDImageCache
|
||||
|
||||
- (id<SDWebImageOperation>)queryImageForKey:(NSString *)key options:(SDWebImageOptions)options context:(nullable SDWebImageContext *)context completion:(nullable SDImageCacheQueryCompletionBlock)completionBlock {
|
||||
return [self queryImageForKey:key options:options context:context cacheType:SDImageCacheTypeAll completion:completionBlock];
|
||||
}
|
||||
|
||||
- (id<SDWebImageOperation>)queryImageForKey:(NSString *)key options:(SDWebImageOptions)options context:(nullable SDWebImageContext *)context cacheType:(SDImageCacheType)cacheType completion:(nullable SDImageCacheQueryCompletionBlock)completionBlock {
|
||||
SDImageCacheOptions cacheOptions = 0;
|
||||
if (options & SDWebImageQueryMemoryData) cacheOptions |= SDImageCacheQueryMemoryData;
|
||||
if (options & SDWebImageQueryMemoryDataSync) cacheOptions |= SDImageCacheQueryMemoryDataSync;
|
||||
|
@ -709,7 +738,7 @@
|
|||
if (options & SDWebImagePreloadAllFrames) cacheOptions |= SDImageCachePreloadAllFrames;
|
||||
if (options & SDWebImageMatchAnimatedImageClass) cacheOptions |= SDImageCacheMatchAnimatedImageClass;
|
||||
|
||||
return [self queryCacheOperationForKey:key options:cacheOptions context:context done:completionBlock];
|
||||
return [self queryCacheOperationForKey:key options:cacheOptions context:context cacheType:cacheType done:completionBlock];
|
||||
}
|
||||
|
||||
- (void)storeImage:(UIImage *)image imageData:(NSData *)imageData forKey:(nullable NSString *)key cacheType:(SDImageCacheType)cacheType completion:(nullable SDWebImageNoParamsBlock)completionBlock {
|
||||
|
|
|
@ -36,6 +36,7 @@ typedef NS_ENUM(NSInteger, SDImageCacheType) {
|
|||
};
|
||||
|
||||
typedef void(^SDImageCacheCheckCompletionBlock)(BOOL isInCache);
|
||||
typedef void(^SDImageCacheQueryDataCompletionBlock)(NSData * _Nullable data);
|
||||
typedef void(^SDImageCacheCalculateSizeBlock)(NSUInteger fileCount, NSUInteger totalSize);
|
||||
typedef NSString * _Nullable (^SDImageCacheAdditionalCachePathBlock)(NSString * _Nonnull key);
|
||||
typedef void(^SDImageCacheQueryCompletionBlock)(UIImage * _Nullable image, NSData * _Nullable data, SDImageCacheType cacheType);
|
||||
|
@ -76,6 +77,23 @@ FOUNDATION_EXPORT UIImage * _Nullable SDImageCacheDecodeImageData(NSData * _Nonn
|
|||
context:(nullable SDWebImageContext *)context
|
||||
completion:(nullable SDImageCacheQueryCompletionBlock)completionBlock;
|
||||
|
||||
/**
|
||||
Query the cached image from image cache for given key. The operation can be used to cancel the query.
|
||||
If image is cached in memory, completion is called synchronously, else aynchronously and depends on the options arg (See `SDWebImageQueryDiskSync`)
|
||||
|
||||
@param key The image cache key
|
||||
@param options A mask to specify options to use for this query
|
||||
@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.
|
||||
@param cacheType Specify where to query the cache from. By default we use `.all`, which means both memory cache and disk cache. You can choose to query memory only or disk only as well. Pass `.none` is invalid and callback with nil immediatelly.
|
||||
@param completionBlock The completion block. Will not get called if the operation is cancelled
|
||||
@return The operation for this query
|
||||
*/
|
||||
- (nullable id<SDWebImageOperation>)queryImageForKey:(nullable NSString *)key
|
||||
options:(SDWebImageOptions)options
|
||||
context:(nullable SDWebImageContext *)context
|
||||
cacheType:(SDImageCacheType)cacheType
|
||||
completion:(nullable SDImageCacheQueryCompletionBlock)completionBlock;
|
||||
|
||||
/**
|
||||
Store the image into image cache for the given key. If cache type is memory only, completion is called synchronously, else aynchronously.
|
||||
|
||||
|
|
|
@ -85,6 +85,10 @@
|
|||
#pragma mark - SDImageCache
|
||||
|
||||
- (id<SDWebImageOperation>)queryImageForKey:(NSString *)key options:(SDWebImageOptions)options context:(SDWebImageContext *)context completion:(SDImageCacheQueryCompletionBlock)completionBlock {
|
||||
return [self queryImageForKey:key options:options context:context cacheType:SDImageCacheTypeAll completion:completionBlock];
|
||||
}
|
||||
|
||||
- (id<SDWebImageOperation>)queryImageForKey:(NSString *)key options:(SDWebImageOptions)options context:(SDWebImageContext *)context cacheType:(SDImageCacheType)cacheType completion:(SDImageCacheQueryCompletionBlock)completionBlock {
|
||||
if (!key) {
|
||||
return nil;
|
||||
}
|
||||
|
@ -93,30 +97,30 @@
|
|||
if (count == 0) {
|
||||
return nil;
|
||||
} else if (count == 1) {
|
||||
return [caches.firstObject queryImageForKey:key options:options context:context completion:completionBlock];
|
||||
return [caches.firstObject queryImageForKey:key options:options context:context cacheType:cacheType completion:completionBlock];
|
||||
}
|
||||
switch (self.queryOperationPolicy) {
|
||||
case SDImageCachesManagerOperationPolicyHighestOnly: {
|
||||
id<SDImageCache> cache = caches.lastObject;
|
||||
return [cache queryImageForKey:key options:options context:context completion:completionBlock];
|
||||
return [cache queryImageForKey:key options:options context:context cacheType:cacheType completion:completionBlock];
|
||||
}
|
||||
break;
|
||||
case SDImageCachesManagerOperationPolicyLowestOnly: {
|
||||
id<SDImageCache> cache = caches.firstObject;
|
||||
return [cache queryImageForKey:key options:options context:context completion:completionBlock];
|
||||
return [cache queryImageForKey:key options:options context:context cacheType:cacheType completion:completionBlock];
|
||||
}
|
||||
break;
|
||||
case SDImageCachesManagerOperationPolicyConcurrent: {
|
||||
SDImageCachesManagerOperation *operation = [SDImageCachesManagerOperation new];
|
||||
[operation beginWithTotalCount:caches.count];
|
||||
[self concurrentQueryImageForKey:key options:options context:context completion:completionBlock enumerator:caches.reverseObjectEnumerator operation:operation];
|
||||
[self concurrentQueryImageForKey:key options:options context:context cacheType:cacheType completion:completionBlock enumerator:caches.reverseObjectEnumerator operation:operation];
|
||||
return operation;
|
||||
}
|
||||
break;
|
||||
case SDImageCachesManagerOperationPolicySerial: {
|
||||
SDImageCachesManagerOperation *operation = [SDImageCachesManagerOperation new];
|
||||
[operation beginWithTotalCount:caches.count];
|
||||
[self serialQueryImageForKey:key options:options context:context completion:completionBlock enumerator:caches.reverseObjectEnumerator operation:operation];
|
||||
[self serialQueryImageForKey:key options:options context:context cacheType:cacheType completion:completionBlock enumerator:caches.reverseObjectEnumerator operation:operation];
|
||||
return operation;
|
||||
}
|
||||
break;
|
||||
|
@ -279,11 +283,11 @@
|
|||
|
||||
#pragma mark - Concurrent Operation
|
||||
|
||||
- (void)concurrentQueryImageForKey:(NSString *)key options:(SDWebImageOptions)options context:(SDWebImageContext *)context completion:(SDImageCacheQueryCompletionBlock)completionBlock enumerator:(NSEnumerator<id<SDImageCache>> *)enumerator operation:(SDImageCachesManagerOperation *)operation {
|
||||
- (void)concurrentQueryImageForKey:(NSString *)key options:(SDWebImageOptions)options context:(SDWebImageContext *)context cacheType:(SDImageCacheType)queryCacheType completion:(SDImageCacheQueryCompletionBlock)completionBlock enumerator:(NSEnumerator<id<SDImageCache>> *)enumerator operation:(SDImageCachesManagerOperation *)operation {
|
||||
NSParameterAssert(enumerator);
|
||||
NSParameterAssert(operation);
|
||||
for (id<SDImageCache> cache in enumerator) {
|
||||
[cache queryImageForKey:key options:options context:context completion:^(UIImage * _Nullable image, NSData * _Nullable data, SDImageCacheType cacheType) {
|
||||
[cache queryImageForKey:key options:options context:context cacheType:queryCacheType completion:^(UIImage * _Nullable image, NSData * _Nullable data, SDImageCacheType cacheType) {
|
||||
if (operation.isCancelled) {
|
||||
// Cancelled
|
||||
return;
|
||||
|
@ -422,7 +426,7 @@
|
|||
|
||||
#pragma mark - Serial Operation
|
||||
|
||||
- (void)serialQueryImageForKey:(NSString *)key options:(SDWebImageOptions)options context:(SDWebImageContext *)context completion:(SDImageCacheQueryCompletionBlock)completionBlock enumerator:(NSEnumerator<id<SDImageCache>> *)enumerator operation:(SDImageCachesManagerOperation *)operation {
|
||||
- (void)serialQueryImageForKey:(NSString *)key options:(SDWebImageOptions)options context:(SDWebImageContext *)context cacheType:(SDImageCacheType)queryCacheType completion:(SDImageCacheQueryCompletionBlock)completionBlock enumerator:(NSEnumerator<id<SDImageCache>> *)enumerator operation:(SDImageCachesManagerOperation *)operation {
|
||||
NSParameterAssert(enumerator);
|
||||
NSParameterAssert(operation);
|
||||
id<SDImageCache> cache = enumerator.nextObject;
|
||||
|
@ -435,7 +439,7 @@
|
|||
return;
|
||||
}
|
||||
@weakify(self);
|
||||
[cache queryImageForKey:key options:options context:context completion:^(UIImage * _Nullable image, NSData * _Nullable data, SDImageCacheType cacheType) {
|
||||
[cache queryImageForKey:key options:options context:context cacheType:queryCacheType completion:^(UIImage * _Nullable image, NSData * _Nullable data, SDImageCacheType cacheType) {
|
||||
@strongify(self);
|
||||
if (operation.isCancelled) {
|
||||
// Cancelled
|
||||
|
@ -455,7 +459,7 @@
|
|||
return;
|
||||
}
|
||||
// Next
|
||||
[self serialQueryImageForKey:key options:options context:context completion:completionBlock enumerator:enumerator operation:operation];
|
||||
[self serialQueryImageForKey:key options:options context:context cacheType:queryCacheType completion:completionBlock enumerator:enumerator operation:operation];
|
||||
}];
|
||||
}
|
||||
|
||||
|
|
|
@ -259,6 +259,12 @@ FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextImageP
|
|||
*/
|
||||
FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextImageThumbnailPixelSize;
|
||||
|
||||
/**
|
||||
A SDImageCacheType raw value which specify the source of cache to query. Specify `SDImageCacheTypeDisk` to query from disk cache only; `SDImageCacheTypeMemory` to query from memory only. And `SDImageCacheTypeAll` to query from both memory cache and disk cache. Specify `SDImageCacheTypeNone` is invalid and totally ignore the cache query.
|
||||
If not provide or the value is invalid, we will use `SDImageCacheTypeAll`. (NSNumber)
|
||||
*/
|
||||
FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextQueryCacheType;
|
||||
|
||||
/**
|
||||
A SDImageCacheType raw value which specify the store cache type when the image has just been downloaded and will be stored to the cache. Specify `SDImageCacheTypeNone` to disable cache storage; `SDImageCacheTypeDisk` to store in disk cache only; `SDImageCacheTypeMemory` to store in memory only. And `SDImageCacheTypeAll` to store in both memory cache and disk cache.
|
||||
If you use image transformer feature, this actually apply for the transformed image, but not the original image itself. Use `SDWebImageContextOriginalStoreCacheType` if you want to control the original image's store cache type at the same time.
|
||||
|
|
|
@ -127,6 +127,7 @@ SDWebImageContextOption const SDWebImageContextImageTransformer = @"imageTransfo
|
|||
SDWebImageContextOption const SDWebImageContextImageScaleFactor = @"imageScaleFactor";
|
||||
SDWebImageContextOption const SDWebImageContextImagePreserveAspectRatio = @"imagePreserveAspectRatio";
|
||||
SDWebImageContextOption const SDWebImageContextImageThumbnailPixelSize = @"imageThumbnailPixelSize";
|
||||
SDWebImageContextOption const SDWebImageContextQueryCacheType = @"queryCacheType";
|
||||
SDWebImageContextOption const SDWebImageContextStoreCacheType = @"storeCacheType";
|
||||
SDWebImageContextOption const SDWebImageContextOriginalStoreCacheType = @"originalStoreCacheType";
|
||||
SDWebImageContextOption const SDWebImageContextAnimatedImageClass = @"animatedImageClass";
|
||||
|
|
|
@ -220,10 +220,15 @@ static id<SDImageLoader> _defaultImageLoader;
|
|||
}
|
||||
// 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];
|
||||
}
|
||||
if (shouldQueryCache) {
|
||||
NSString *key = [self cacheKeyForURL:url context:context];
|
||||
@weakify(operation);
|
||||
operation.cacheOperation = [imageCache queryImageForKey:key options:options context:context completion:^(UIImage * _Nullable cachedImage, NSData * _Nullable cachedData, SDImageCacheType cacheType) {
|
||||
operation.cacheOperation = [imageCache queryImageForKey:key options:options context:context cacheType:queryCacheType completion:^(UIImage * _Nullable cachedImage, NSData * _Nullable cachedData, SDImageCacheType cacheType) {
|
||||
@strongify(operation);
|
||||
if (!operation || operation.isCancelled) {
|
||||
// Image combined operation cancelled by user
|
||||
|
|
|
@ -610,7 +610,7 @@ static NSString *kTestImageKeyPNG = @"TestImageKey.png";
|
|||
- (void)test50SDImageCacheQueryOp {
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"SDImageCache query op works"];
|
||||
[[SDImageCache sharedImageCache] storeImage:[self testJPEGImage] forKey:kTestImageKeyJPEG toDisk:NO completion:nil];
|
||||
[[SDImageCachesManager sharedManager] queryImageForKey:kTestImageKeyJPEG options:0 context:nil completion:^(UIImage * _Nullable image, NSData * _Nullable data, SDImageCacheType cacheType) {
|
||||
[[SDImageCachesManager sharedManager] queryImageForKey:kTestImageKeyJPEG options:0 context:nil cacheType:SDImageCacheTypeAll completion:^(UIImage * _Nullable image, NSData * _Nullable data, SDImageCacheType cacheType) {
|
||||
expect(image).notTo.beNil();
|
||||
[expectation fulfill];
|
||||
}];
|
||||
|
@ -680,7 +680,7 @@ static NSString *kTestImageKeyPNG = @"TestImageKey.png";
|
|||
cachesManager.removeOperationPolicy = SDImageCachesManagerOperationPolicyLowestOnly;
|
||||
cachesManager.containsOperationPolicy = SDImageCachesManagerOperationPolicyLowestOnly;
|
||||
cachesManager.clearOperationPolicy = SDImageCachesManagerOperationPolicyLowestOnly;
|
||||
[cachesManager queryImageForKey:kTestImageKeyJPEG options:0 context:nil completion:^(UIImage * _Nullable image, NSData * _Nullable data, SDImageCacheType cacheType) {
|
||||
[cachesManager queryImageForKey:kTestImageKeyJPEG options:0 context:nil cacheType:SDImageCacheTypeAll completion:^(UIImage * _Nullable image, NSData * _Nullable data, SDImageCacheType cacheType) {
|
||||
expect(image).to.beNil();
|
||||
}];
|
||||
[cachesManager storeImage:[self testJPEGImage] imageData:nil forKey:kTestImageKeyJPEG cacheType:SDImageCacheTypeMemory completion:nil];
|
||||
|
@ -699,7 +699,7 @@ static NSString *kTestImageKeyPNG = @"TestImageKey.png";
|
|||
cachesManager.removeOperationPolicy = SDImageCachesManagerOperationPolicyHighestOnly;
|
||||
cachesManager.containsOperationPolicy = SDImageCachesManagerOperationPolicyHighestOnly;
|
||||
cachesManager.clearOperationPolicy = SDImageCachesManagerOperationPolicyHighestOnly;
|
||||
[cachesManager queryImageForKey:kTestImageKeyPNG options:0 context:nil completion:^(UIImage * _Nullable image, NSData * _Nullable data, SDImageCacheType cacheType) {
|
||||
[cachesManager queryImageForKey:kTestImageKeyPNG options:0 context:nil cacheType:SDImageCacheTypeAll completion:^(UIImage * _Nullable image, NSData * _Nullable data, SDImageCacheType cacheType) {
|
||||
expect(image).to.beNil();
|
||||
}];
|
||||
[cachesManager storeImage:[self testPNGImage] imageData:nil forKey:kTestImageKeyPNG cacheType:SDImageCacheTypeMemory completion:nil];
|
||||
|
@ -732,7 +732,7 @@ static NSString *kTestImageKeyPNG = @"TestImageKey.png";
|
|||
cachesManager.removeOperationPolicy = SDImageCachesManagerOperationPolicyConcurrent;
|
||||
cachesManager.containsOperationPolicy = SDImageCachesManagerOperationPolicyConcurrent;
|
||||
cachesManager.clearOperationPolicy = SDImageCachesManagerOperationPolicyConcurrent;
|
||||
[cachesManager queryImageForKey:kConcurrentTestImageKey options:0 context:nil completion:nil];
|
||||
[cachesManager queryImageForKey:kConcurrentTestImageKey options:0 context:nil cacheType:SDImageCacheTypeAll completion:nil];
|
||||
[cachesManager storeImage:[self testJPEGImage] imageData:nil forKey:kConcurrentTestImageKey cacheType:SDImageCacheTypeMemory completion:nil];
|
||||
[cachesManager removeImageForKey:kConcurrentTestImageKey cacheType:SDImageCacheTypeMemory completion:nil];
|
||||
[cachesManager clearWithCacheType:SDImageCacheTypeMemory completion:nil];
|
||||
|
@ -772,7 +772,7 @@ static NSString *kTestImageKeyPNG = @"TestImageKey.png";
|
|||
cachesManager.removeOperationPolicy = SDImageCachesManagerOperationPolicySerial;
|
||||
cachesManager.containsOperationPolicy = SDImageCachesManagerOperationPolicySerial;
|
||||
cachesManager.clearOperationPolicy = SDImageCachesManagerOperationPolicySerial;
|
||||
[cachesManager queryImageForKey:kSerialTestImageKey options:0 context:nil completion:nil];
|
||||
[cachesManager queryImageForKey:kSerialTestImageKey options:0 context:nil cacheType:SDImageCacheTypeAll completion:nil];
|
||||
[cachesManager storeImage:[self testJPEGImage] imageData:nil forKey:kSerialTestImageKey cacheType:SDImageCacheTypeMemory completion:nil];
|
||||
[cachesManager removeImageForKey:kSerialTestImageKey cacheType:SDImageCacheTypeMemory completion:nil];
|
||||
[cachesManager clearWithCacheType:SDImageCacheTypeMemory completion:nil];
|
||||
|
@ -793,6 +793,41 @@ static NSString *kTestImageKeyPNG = @"TestImageKey.png";
|
|||
[self waitForExpectationsWithCommonTimeout];
|
||||
}
|
||||
|
||||
- (void)test58CustomImageCache {
|
||||
NSString *cachePath = [[self userCacheDirectory] stringByAppendingPathComponent:@"custom"];
|
||||
SDImageCacheConfig *config = [[SDImageCacheConfig alloc] init];
|
||||
SDWebImageTestCache *cache = [[SDWebImageTestCache alloc] initWithCachePath:cachePath config:config];
|
||||
expect(cache.memoryCache).notTo.beNil();
|
||||
expect(cache.diskCache).notTo.beNil();
|
||||
|
||||
// Clear
|
||||
[cache clearWithCacheType:SDImageCacheTypeAll completion:nil];
|
||||
// Store
|
||||
UIImage *image1 = self.testJPEGImage;
|
||||
NSString *key1 = @"testJPEGImage";
|
||||
[cache storeImage:image1 imageData:nil forKey:key1 cacheType:SDImageCacheTypeAll completion:nil];
|
||||
// Contain
|
||||
[cache containsImageForKey:key1 cacheType:SDImageCacheTypeAll completion:^(SDImageCacheType containsCacheType) {
|
||||
expect(containsCacheType).equal(SDImageCacheTypeMemory);
|
||||
}];
|
||||
// Query
|
||||
[cache queryImageForKey:key1 options:0 context:nil cacheType:SDImageCacheTypeAll completion:^(UIImage * _Nullable image, NSData * _Nullable data, SDImageCacheType cacheType) {
|
||||
expect(image).equal(image1);
|
||||
expect(data).beNil();
|
||||
expect(cacheType).equal(SDImageCacheTypeMemory);
|
||||
}];
|
||||
// Remove
|
||||
[cache removeImageForKey:key1 cacheType:SDImageCacheTypeAll completion:nil];
|
||||
// Contain
|
||||
[cache containsImageForKey:key1 cacheType:SDImageCacheTypeAll completion:^(SDImageCacheType containsCacheType) {
|
||||
expect(containsCacheType).equal(SDImageCacheTypeNone);
|
||||
}];
|
||||
// Clear
|
||||
[cache clearWithCacheType:SDImageCacheTypeAll completion:nil];
|
||||
NSArray<NSString *> *cacheFiles = [cache.diskCache.fileManager contentsOfDirectoryAtPath:cachePath error:nil];
|
||||
expect(cacheFiles.count).equal(0);
|
||||
}
|
||||
|
||||
#pragma mark Helper methods
|
||||
|
||||
- (UIImage *)testJPEGImage {
|
||||
|
|
|
@ -474,7 +474,6 @@
|
|||
[self waitForExpectationsWithCommonTimeout];
|
||||
}
|
||||
|
||||
#if SD_UIKIT
|
||||
- (void)test22ThatCustomDecoderWorksForImageDownload {
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"Custom decoder for SDWebImageDownloader not works"];
|
||||
SDWebImageDownloader *downloader = [[SDWebImageDownloader alloc] init];
|
||||
|
@ -487,8 +486,8 @@
|
|||
UIImage *testJPEGImage = [[UIImage alloc] initWithContentsOfFile:testJPEGImagePath];
|
||||
|
||||
[downloader downloadImageWithURL:testImageURL options:0 progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, BOOL finished) {
|
||||
NSData *data1 = UIImagePNGRepresentation(testJPEGImage);
|
||||
NSData *data2 = UIImagePNGRepresentation(image);
|
||||
NSData *data1 = [testJPEGImage sd_imageDataAsFormat:SDImageFormatPNG];
|
||||
NSData *data2 = [image sd_imageDataAsFormat:SDImageFormatPNG];
|
||||
if (![data1 isEqualToData:data2]) {
|
||||
XCTFail(@"The image data is not equal to cutom decoder, check -[SDWebImageTestDecoder decodedImageWithData:]");
|
||||
}
|
||||
|
@ -499,7 +498,6 @@
|
|||
[self waitForExpectationsWithCommonTimeout];
|
||||
[downloader invalidateSessionAndCancel:YES];
|
||||
}
|
||||
#endif
|
||||
|
||||
- (void)test23ThatDownloadRequestModifierWorks {
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"Download request modifier not works"];
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
#import "SDTestCase.h"
|
||||
#import "SDWebImageTestTransformer.h"
|
||||
#import "SDWebImageTestCache.h"
|
||||
#import "SDWebImageTestLoader.h"
|
||||
|
||||
@interface SDWebImageManagerTests : SDTestCase
|
||||
|
||||
|
@ -268,6 +270,53 @@
|
|||
}];
|
||||
}
|
||||
|
||||
- (void)test14ThatCustomCacheAndLoaderWorks {
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"Custom Cache and Loader during manger query"];
|
||||
NSURL *url = [NSURL URLWithString:@"http://via.placeholder.com/100x100.png"];
|
||||
SDWebImageContext *context = @{
|
||||
SDWebImageContextImageCache : SDWebImageTestCache.sharedCache,
|
||||
SDWebImageContextImageLoader : SDWebImageTestLoader.sharedLoader
|
||||
};
|
||||
[SDWebImageTestCache.sharedCache clearWithCacheType:SDImageCacheTypeAll completion:nil];
|
||||
[SDWebImageManager.sharedManager loadImageWithURL:url options:SDWebImageWaitStoreCache context:context progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
|
||||
expect(image).notTo.beNil();
|
||||
expect(image.size.width).equal(100);
|
||||
expect(image.size.height).equal(100);
|
||||
expect(data).notTo.beNil();
|
||||
NSString *cacheKey = [SDWebImageManager.sharedManager cacheKeyForURL:imageURL];
|
||||
// Check Disk Cache (SDWebImageWaitStoreCache behavior)
|
||||
[SDWebImageTestCache.sharedCache containsImageForKey:cacheKey cacheType:SDImageCacheTypeDisk completion:^(SDImageCacheType containsCacheType) {
|
||||
expect(containsCacheType).equal(SDImageCacheTypeDisk);
|
||||
[expectation fulfill];
|
||||
}];
|
||||
}];
|
||||
|
||||
[self waitForExpectationsWithCommonTimeout];
|
||||
}
|
||||
|
||||
- (void)test15ThatQueryCacheTypeWork {
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"Image query cache type works"];
|
||||
NSURL *url = [NSURL URLWithString:@"http://via.placeholder.com/101x101.png"];
|
||||
NSString *key = [SDWebImageManager.sharedManager cacheKeyForURL:url];
|
||||
NSData *testImageData = [NSData dataWithContentsOfFile:[self testJPEGPath]];
|
||||
[SDImageCache.sharedImageCache storeImageDataToDisk:testImageData forKey:key];
|
||||
|
||||
// Query memory first
|
||||
[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) {
|
||||
expect(image).beNil();
|
||||
expect(cacheType).equal(SDImageCacheTypeNone);
|
||||
// Query disk secondly
|
||||
[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) {
|
||||
expect(image2).notTo.beNil();
|
||||
expect(cacheType2).equal(SDImageCacheTypeDisk);
|
||||
[SDImageCache.sharedImageCache removeImageFromDiskForKey:key];
|
||||
[expectation fulfill];
|
||||
}];
|
||||
}];
|
||||
|
||||
[self waitForExpectationsWithCommonTimeout];
|
||||
}
|
||||
|
||||
- (NSString *)testJPEGPath {
|
||||
NSBundle *testBundle = [NSBundle bundleForClass:[self class]];
|
||||
return [testBundle pathForResource:@"TestImage" ofType:@"jpg"];
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
|
||||
#import <SDWebImage/SDMemoryCache.h>
|
||||
#import <SDWebImage/SDDiskCache.h>
|
||||
#import <SDWebImage/SDImageCacheDefine.h>
|
||||
|
||||
// A really naive implementation of custom memory cache and disk cache
|
||||
|
||||
@interface SDWebImageTestMemoryCache : NSObject <SDMemoryCache>
|
||||
|
||||
@property (nonatomic, strong, nonnull) SDImageCacheConfig *config;
|
||||
|
@ -26,3 +26,16 @@
|
|||
@property (nonatomic, strong, nonnull) NSFileManager *fileManager;
|
||||
|
||||
@end
|
||||
|
||||
// A really naive implementation of custom image cache using memory cache and disk cache
|
||||
@interface SDWebImageTestCache : NSObject <SDImageCache>
|
||||
|
||||
@property (nonatomic, strong, nonnull) SDImageCacheConfig *config;
|
||||
@property (nonatomic, strong, nonnull) SDWebImageTestMemoryCache *memoryCache;
|
||||
@property (nonatomic, strong, nonnull) SDWebImageTestDiskCache *diskCache;
|
||||
|
||||
- (nullable instancetype)initWithCachePath:(nonnull NSString *)cachePath config:(nonnull SDImageCacheConfig *)config;
|
||||
|
||||
@property (nonatomic, class, readonly, nonnull) SDWebImageTestCache *sharedCache;
|
||||
|
||||
@end
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*/
|
||||
|
||||
#import "SDWebImageTestCache.h"
|
||||
#import <SDWebImage/SDImageCacheConfig.h>
|
||||
#import <SDWebImage/SDWebImage.h>
|
||||
#import "SDFileAttributeHelper.h"
|
||||
|
||||
static NSString * const SDWebImageTestDiskCacheExtendedAttributeName = @"com.hackemist.SDWebImageTestDiskCache";
|
||||
|
@ -49,7 +49,7 @@ static NSString * const SDWebImageTestDiskCacheExtendedAttributeName = @"com.hac
|
|||
@implementation SDWebImageTestDiskCache
|
||||
|
||||
- (nullable NSString *)cachePathForKey:(nonnull NSString *)key {
|
||||
return [self.cachePath stringByAppendingPathComponent:key];
|
||||
return [self.cachePath stringByAppendingPathComponent:key.lastPathComponent];
|
||||
}
|
||||
|
||||
- (BOOL)containsDataForKey:(nonnull NSString *)key {
|
||||
|
@ -72,7 +72,10 @@ static NSString * const SDWebImageTestDiskCacheExtendedAttributeName = @"com.hac
|
|||
}
|
||||
|
||||
- (void)removeAllData {
|
||||
[self.fileManager removeItemAtPath:self.cachePath error:nil];
|
||||
for (NSString *path in [self.fileManager subpathsAtPath:self.cachePath]) {
|
||||
NSString *filePath = [self.cachePath stringByAppendingPathComponent:path];
|
||||
[self.fileManager removeItemAtPath:filePath error:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)removeDataForKey:(nonnull NSString *)key {
|
||||
|
@ -122,3 +125,170 @@ static NSString * const SDWebImageTestDiskCacheExtendedAttributeName = @"com.hac
|
|||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation SDWebImageTestCache
|
||||
|
||||
+ (SDWebImageTestCache *)sharedCache {
|
||||
static dispatch_once_t onceToken;
|
||||
static SDWebImageTestCache *cache;
|
||||
dispatch_once(&onceToken, ^{
|
||||
NSString *cachePath = [[self userCacheDirectory] stringByAppendingPathComponent:@"SDWebImageTestCache"];
|
||||
SDImageCacheConfig *config = SDImageCacheConfig.defaultCacheConfig;
|
||||
cache = [[SDWebImageTestCache alloc] initWithCachePath:cachePath config:config];
|
||||
});
|
||||
return cache;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCachePath:(NSString *)cachePath config:(SDImageCacheConfig *)config {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.config = config;
|
||||
self.memoryCache = [[SDWebImageTestMemoryCache alloc] initWithConfig:config];
|
||||
self.diskCache = [[SDWebImageTestDiskCache alloc] initWithCachePath:cachePath config:config];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)clearWithCacheType:(SDImageCacheType)cacheType completion:(nullable SDWebImageNoParamsBlock)completionBlock {
|
||||
switch (cacheType) {
|
||||
case SDImageCacheTypeNone:
|
||||
break;
|
||||
case SDImageCacheTypeMemory:
|
||||
[self.memoryCache removeAllObjects];
|
||||
break;
|
||||
case SDImageCacheTypeDisk:
|
||||
[self.diskCache removeAllData];
|
||||
break;
|
||||
case SDImageCacheTypeAll:
|
||||
[self.memoryCache removeAllObjects];
|
||||
[self.diskCache removeAllData];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (completionBlock) {
|
||||
completionBlock();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)containsImageForKey:(nullable NSString *)key cacheType:(SDImageCacheType)cacheType completion:(nullable SDImageCacheContainsCompletionBlock)completionBlock {
|
||||
SDImageCacheType containsCacheType = SDImageCacheTypeNone;
|
||||
switch (cacheType) {
|
||||
case SDImageCacheTypeNone:
|
||||
break;
|
||||
case SDImageCacheTypeMemory:
|
||||
containsCacheType = [self.memoryCache objectForKey:key] ? SDImageCacheTypeMemory : SDImageCacheTypeNone;
|
||||
break;
|
||||
case SDImageCacheTypeDisk:
|
||||
containsCacheType = [self.diskCache containsDataForKey:key] ? SDImageCacheTypeDisk : SDImageCacheTypeNone;
|
||||
break;
|
||||
case SDImageCacheTypeAll:
|
||||
if ([self.memoryCache objectForKey:key]) {
|
||||
containsCacheType = SDImageCacheTypeMemory;
|
||||
} else if ([self.diskCache containsDataForKey:key]) {
|
||||
containsCacheType = SDImageCacheTypeDisk;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (completionBlock) {
|
||||
completionBlock(containsCacheType);
|
||||
}
|
||||
}
|
||||
|
||||
- (nullable id<SDWebImageOperation>)queryImageForKey:(nullable NSString *)key options:(SDWebImageOptions)options context:(nullable SDWebImageContext *)context completion:(nullable SDImageCacheQueryCompletionBlock)completionBlock {
|
||||
return [self queryImageForKey:key options:options context:context cacheType:SDImageCacheTypeAll completion:completionBlock];
|
||||
}
|
||||
|
||||
- (nullable id<SDWebImageOperation>)queryImageForKey:(nullable NSString *)key options:(SDWebImageOptions)options context:(nullable SDWebImageContext *)context cacheType:(SDImageCacheType)cacheType completion:(nullable SDImageCacheQueryCompletionBlock)completionBlock {
|
||||
UIImage *image;
|
||||
NSData *data;
|
||||
SDImageCacheType resultCacheType = SDImageCacheTypeNone;
|
||||
switch (cacheType) {
|
||||
case SDImageCacheTypeNone:
|
||||
break;
|
||||
case SDImageCacheTypeMemory:
|
||||
image = [self.memoryCache objectForKey:key];
|
||||
if (image) {
|
||||
resultCacheType = SDImageCacheTypeMemory;
|
||||
}
|
||||
break;
|
||||
case SDImageCacheTypeDisk:
|
||||
data = [self.diskCache dataForKey:key];
|
||||
image = [UIImage sd_imageWithData:data];
|
||||
if (data) {
|
||||
resultCacheType = SDImageCacheTypeDisk;
|
||||
}
|
||||
break;
|
||||
case SDImageCacheTypeAll:
|
||||
image = [self.memoryCache objectForKey:key];
|
||||
if (image) {
|
||||
resultCacheType = SDImageCacheTypeMemory;
|
||||
} else {
|
||||
data = [self.diskCache dataForKey:key];
|
||||
image = [UIImage sd_imageWithData:data];
|
||||
if (data) {
|
||||
resultCacheType = SDImageCacheTypeDisk;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (completionBlock) {
|
||||
completionBlock(image, data, resultCacheType);
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)removeImageForKey:(nullable NSString *)key cacheType:(SDImageCacheType)cacheType completion:(nullable SDWebImageNoParamsBlock)completionBlock {
|
||||
switch (cacheType) {
|
||||
case SDImageCacheTypeNone:
|
||||
break;
|
||||
case SDImageCacheTypeMemory:
|
||||
[self.memoryCache removeObjectForKey:key];
|
||||
break;
|
||||
case SDImageCacheTypeDisk:
|
||||
[self.diskCache removeDataForKey:key];
|
||||
break;
|
||||
case SDImageCacheTypeAll:
|
||||
[self.memoryCache removeObjectForKey:key];
|
||||
[self.diskCache removeDataForKey:key];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (completionBlock) {
|
||||
completionBlock();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)storeImage:(nullable UIImage *)image imageData:(nullable NSData *)imageData forKey:(nullable NSString *)key cacheType:(SDImageCacheType)cacheType completion:(nullable SDWebImageNoParamsBlock)completionBlock {
|
||||
switch (cacheType) {
|
||||
case SDImageCacheTypeNone:
|
||||
break;
|
||||
case SDImageCacheTypeMemory:
|
||||
[self.memoryCache setObject:image forKey:key];
|
||||
break;
|
||||
case SDImageCacheTypeDisk:
|
||||
[self.diskCache setData:imageData forKey:key];
|
||||
break;
|
||||
case SDImageCacheTypeAll:
|
||||
[self.memoryCache setObject:image forKey:key];
|
||||
[self.diskCache setData:imageData forKey:key];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (completionBlock) {
|
||||
completionBlock();
|
||||
}
|
||||
}
|
||||
|
||||
+ (nullable NSString *)userCacheDirectory {
|
||||
NSArray<NSString *> *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
||||
return paths.firstObject;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -13,4 +13,6 @@
|
|||
// A really naive implementation of custom image loader using `NSURLSession`
|
||||
@interface SDWebImageTestLoader : NSObject <SDImageLoader>
|
||||
|
||||
@property (nonatomic, class, readonly, nonnull) SDWebImageTestLoader *sharedLoader;
|
||||
|
||||
@end
|
||||
|
|
|
@ -16,6 +16,15 @@
|
|||
|
||||
@implementation SDWebImageTestLoader
|
||||
|
||||
+ (SDWebImageTestLoader *)sharedLoader {
|
||||
static dispatch_once_t onceToken;
|
||||
static SDWebImageTestLoader *loader;
|
||||
dispatch_once(&onceToken, ^{
|
||||
loader = [[SDWebImageTestLoader alloc] init];
|
||||
});
|
||||
return loader;
|
||||
}
|
||||
|
||||
- (BOOL)canRequestImageForURL:(NSURL *)url {
|
||||
return YES;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue