Move that `maxMemoryCost` and `maxMemoryCountLimit` to config property. Add sync version API `diskImageDataExistsWithKey`

This commit is contained in:
DreamPiggy 2018-01-05 12:59:21 +08:00
parent 85e389ee7a
commit 030a3378da
3 changed files with 76 additions and 50 deletions

View File

@ -57,16 +57,6 @@ typedef void(^SDWebImageCompletionWithPossibleErrorBlock)(NSError * _Nullable er
*/
@property (nonatomic, nonnull, readonly) SDImageCacheConfig *config;
/**
* The maximum "total cost" of the in-memory image cache. The cost function is the number of pixels held in memory.
*/
@property (assign, nonatomic) NSUInteger maxMemoryCost;
/**
* The maximum number of objects the cache should hold.
*/
@property (assign, nonatomic) NSUInteger maxMemoryCountLimit;
#pragma mark - Singleton and initialization
/**
@ -133,7 +123,7 @@ typedef void(^SDWebImageCompletionWithPossibleErrorBlock)(NSError * _Nullable er
*
* @param image The image to store
* @param key The unique image cache key, usually it's image absolute URL
* @param toDisk Store the image to disk cache if YES
* @param toDisk Store the image to disk cache if YES. If NO, the completion block is called synchronously
* @param completionBlock A block executed after the operation is finished
*/
- (void)storeImage:(nullable UIImage *)image
@ -149,7 +139,7 @@ typedef void(^SDWebImageCompletionWithPossibleErrorBlock)(NSError * _Nullable er
* instead of converting the given image object into a storable/compressed image format in order
* to save quality and CPU
* @param key The unique image cache key, usually it's image absolute URL
* @param toDisk Store the image to disk cache if YES
* @param toDisk Store the image to disk cache if YES. If NO, the completion block is called synchronously
* @param completionBlock A block executed after the operation is finished
*/
- (void)storeImage:(nullable UIImage *)image
@ -173,7 +163,7 @@ typedef void(^SDWebImageCompletionWithPossibleErrorBlock)(NSError * _Nullable er
#pragma mark - Query and Retrieve Ops
/**
* Async check if image exists in disk cache already (does not load the image)
* Asynchronously check if image exists in disk cache already (does not load the image)
*
* @param key the key describing the url
* @param completionBlock the block to be executed when the check is done.
@ -182,7 +172,14 @@ typedef void(^SDWebImageCompletionWithPossibleErrorBlock)(NSError * _Nullable er
- (void)diskImageExistsWithKey:(nullable NSString *)key completion:(nullable SDWebImageCheckCacheCompletionBlock)completionBlock;
/**
* Operation that queries the cache asynchronously and call the completion when done.
* Synchronously check if image data exists in disk cache already (does not load the image)
*
* @param key the key describing the url
*/
- (BOOL)diskImageDataExistsWithKey:(nullable NSString *)key;
/**
* Asynchronously queries the cache with operation and call the completion when done.
*
* @param key The unique key used to store the wanted image
* @param doneBlock The completion block. Will not get called if the operation is cancelled
@ -192,7 +189,7 @@ typedef void(^SDWebImageCompletionWithPossibleErrorBlock)(NSError * _Nullable er
- (nullable NSOperation *)queryCacheOperationForKey:(nullable NSString *)key done:(nullable SDCacheQueryCompletedBlock)doneBlock;
/**
* Operation that queries the cache asynchronously and call the completion when done.
* Asynchronously queries the cache with operation and call the completion when done.
*
* @param key The unique key used to store the wanted image
* @param options A mask to specify options to use for this cache query
@ -203,21 +200,21 @@ typedef void(^SDWebImageCompletionWithPossibleErrorBlock)(NSError * _Nullable er
- (nullable NSOperation *)queryCacheOperationForKey:(nullable NSString *)key options:(SDImageCacheOptions)options done:(nullable SDCacheQueryCompletedBlock)doneBlock;
/**
* Query the memory cache synchronously.
* Synchronously query the memory cache.
*
* @param key The unique key used to store the image
*/
- (nullable UIImage *)imageFromMemoryCacheForKey:(nullable NSString *)key;
/**
* Query the disk cache synchronously.
* Synchronously query the disk cache.
*
* @param key The unique key used to store the image
*/
- (nullable UIImage *)imageFromDiskCacheForKey:(nullable NSString *)key;
/**
* Query the cache (memory and or disk) synchronously after checking the memory cache.
* Synchronously query the cache (memory and or disk) after checking the memory cache.
*
* @param key The unique key used to store the image
*/
@ -226,7 +223,7 @@ typedef void(^SDWebImageCompletionWithPossibleErrorBlock)(NSError * _Nullable er
#pragma mark - Remove Ops
/**
* Remove the image from memory and disk cache asynchronously
* Asynchronously remove the image from memory and disk cache
*
* @param key The unique image cache key
* @param completion A block that should be executed after the image has been removed (optional)
@ -234,10 +231,10 @@ typedef void(^SDWebImageCompletionWithPossibleErrorBlock)(NSError * _Nullable er
- (void)removeImageForKey:(nullable NSString *)key withCompletion:(nullable SDWebImageNoParamsBlock)completion;
/**
* Remove the image from memory and optionally disk cache asynchronously
* Asynchronously remove the image from memory and optionally disk cache
*
* @param key The unique image cache key
* @param fromDisk Also remove cache entry from disk if YES
* @param fromDisk Also remove cache entry from disk if YES. If NO, the completion block is called synchronously
* @param completion A block that should be executed after the image has been removed (optional)
*/
- (void)removeImageForKey:(nullable NSString *)key fromDisk:(BOOL)fromDisk withCompletion:(nullable SDWebImageNoParamsBlock)completion;
@ -245,18 +242,18 @@ typedef void(^SDWebImageCompletionWithPossibleErrorBlock)(NSError * _Nullable er
#pragma mark - Cache clean Ops
/**
* Clear all memory cached images
* Synchronously Clear all memory cached images
*/
- (void)clearMemory;
/**
* Async clear all disk cached images. Non-blocking method - returns immediately.
* Asynchronously clear all disk cached images. Non-blocking method - returns immediately.
* @param completion A block that should be executed after cache expiration completes (optional)
*/
- (void)clearDiskOnCompletion:(nullable SDWebImageNoParamsBlock)completion;
/**
* Async remove all expired cached image from disk. Non-blocking method - returns immediately.
* Asynchronously remove all expired cached image from disk. Non-blocking method - returns immediately.
* @param completionBlock A block that should be executed after cache expiration completes (optional)
*/
- (void)deleteOldFilesWithCompletionBlock:(nullable SDWebImageNoParamsBlock)completionBlock;

View File

@ -11,6 +11,8 @@
#import "NSImage+WebCache.h"
#import "SDWebImageCodersManager.h"
static void * SDImageCacheContext = &SDImageCacheContext;
FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
#if SD_MAC
return image.size.height * image.size.width;
@ -69,6 +71,9 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
_ioQueue = dispatch_queue_create("com.hackemist.SDWebImageCache", DISPATCH_QUEUE_SERIAL);
_config = [[SDImageCacheConfig alloc] init];
// KVO config property which need to be passed
[_config addObserver:self forKeyPath:NSStringFromSelector(@selector(maxMemoryCost)) options:0 context:SDImageCacheContext];
[_config addObserver:self forKeyPath:NSStringFromSelector(@selector(maxMemoryCount)) options:0 context:SDImageCacheContext];
// Init the memory cache
_memCache = [[NSCache alloc] init];
@ -109,6 +114,8 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
}
- (void)dealloc {
[_config removeObserver:self forKeyPath:NSStringFromSelector(@selector(maxMemoryCost)) context:SDImageCacheContext];
[_config removeObserver:self forKeyPath:NSStringFromSelector(@selector(maxMemoryCount)) context:SDImageCacheContext];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
@ -255,12 +262,13 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
// NSFileManager's `createFileAtPath:` is used just for old code compatibility and will not trigger any delegate methods, so it's useless for custom NSFileManager at all.
// And also, NSFileManager's `createFileAtPath:` can only grab underlying POSIX errno, but NSData can grab errors defined in NSCocoaErrorDomain, which is better for user to check.
if (![imageData writeToFile:cachePathForKey options:self.config.diskCacheWritingOptions error:error]) {
if (![imageData writeToURL:fileURL options:self.config.diskCacheWritingOptions error:error]) {
return NO;
}
// disable iCloud backup
if (self.config.shouldDisableiCloud) {
// ignore iCloud backup resource value error
[fileURL setResourceValue:@YES forKey:NSURLIsExcludedFromBackupKey error:nil];
}
@ -271,13 +279,7 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
- (void)diskImageExistsWithKey:(nullable NSString *)key completion:(nullable SDWebImageCheckCacheCompletionBlock)completionBlock {
dispatch_async(_ioQueue, ^{
BOOL exists = [_fileManager fileExistsAtPath:[self defaultCachePathForKey:key]];
// fallback because of https://github.com/rs/SDWebImage/pull/976 that added the extension to the disk file name
// checking the key with and without the extension
if (!exists) {
exists = [_fileManager fileExistsAtPath:[self defaultCachePathForKey:key].stringByDeletingPathExtension];
}
BOOL exists = [self diskImageDataExistsWithKey:key];
if (completionBlock) {
dispatch_async(dispatch_get_main_queue(), ^{
@ -287,6 +289,21 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
});
}
- (BOOL)diskImageDataExistsWithKey:(nullable NSString *)key {
if (!key) {
return NO;
}
BOOL exists = [_fileManager fileExistsAtPath:[self defaultCachePathForKey:key]];
// fallback because of https://github.com/rs/SDWebImage/pull/976 that added the extension to the disk file name
// checking the key with and without the extension
if (!exists) {
exists = [_fileManager fileExistsAtPath:[self defaultCachePathForKey:key].stringByDeletingPathExtension];
}
return exists;
}
- (nullable UIImage *)imageFromMemoryCacheForKey:(nullable NSString *)key {
return [self.memCache objectForKey:key];
}
@ -460,22 +477,18 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
}
# pragma mark - Mem Cache settings
#pragma mark - KVO
- (void)setMaxMemoryCost:(NSUInteger)maxMemoryCost {
self.memCache.totalCostLimit = maxMemoryCost;
}
- (NSUInteger)maxMemoryCost {
return self.memCache.totalCostLimit;
}
- (NSUInteger)maxMemoryCountLimit {
return self.memCache.countLimit;
}
- (void)setMaxMemoryCountLimit:(NSUInteger)maxCountLimit {
self.memCache.countLimit = maxCountLimit;
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
if (context == SDImageCacheContext) {
if ([keyPath isEqualToString:NSStringFromSelector(@selector(maxMemoryCost))]) {
self.memCache.totalCostLimit = self.config.maxMemoryCost;
} else if ([keyPath isEqualToString:NSStringFromSelector(@selector(maxMemoryCount))]) {
self.memCache.countLimit = self.config.maxMemoryCount;
}
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
#pragma mark - Cache clean Ops

View File

@ -12,18 +12,20 @@
@interface SDImageCacheConfig : NSObject
/**
* Decompressing images that are downloaded and cached can improve performance but can consume lot of memory.
* Decompressing images means pre-decoding the image that are downloaded and cached on background queue. This can avoid image view decode it on main queue when rendering. This can improve performance but can consume more memory.
* Defaults to YES. Set this to NO if you are experiencing a crash due to excessive memory consumption.
*/
@property (assign, nonatomic) BOOL shouldDecompressImages;
/**
* disable iCloud backup [defaults to YES]
* Whether or not to disable iCloud backup
* Defaults to YES.
*/
@property (assign, nonatomic) BOOL shouldDisableiCloud;
/**
* use memory cache [defaults to YES]
* Whether or not to use memory cache
* Defaults to YES.
*/
@property (assign, nonatomic) BOOL shouldCacheImagesInMemory;
@ -41,12 +43,26 @@
/**
* The maximum length of time to keep an image in the cache, in seconds.
* Defaults to 1 weak.
*/
@property (assign, nonatomic) NSInteger maxCacheAge;
/**
* The maximum size of the cache, in bytes.
* Defaults to 0. Which means there is no cache size limit.
*/
@property (assign, nonatomic) NSUInteger maxCacheSize;
/**
* The maximum "total cost" of the in-memory image cache. The cost function is the number of pixels held in memory.
* Defaults to 0. Which means there is no memory cost limit.
*/
@property (assign, nonatomic) NSUInteger maxMemoryCost;
/**
* The maximum number of objects the cache should hold.
* Defaults to 0. Which means there is no memory count limit.
*/
@property (assign, nonatomic) NSUInteger maxMemoryCount;
@end