Add option to enable or disable weak memory cache for SDImageCache
This commit is contained in:
parent
e98a9415c6
commit
bfa940352f
|
@ -30,9 +30,13 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
||||||
// Private
|
// Private
|
||||||
@interface SDMemoryCache <KeyType, ObjectType> ()
|
@interface SDMemoryCache <KeyType, ObjectType> ()
|
||||||
|
|
||||||
|
@property (nonatomic, strong, nonnull) SDImageCacheConfig *config;
|
||||||
@property (nonatomic, strong, nonnull) NSMapTable<KeyType, ObjectType> *weakCache; // strong-weak cache
|
@property (nonatomic, strong, nonnull) NSMapTable<KeyType, ObjectType> *weakCache; // strong-weak cache
|
||||||
@property (nonatomic, strong, nonnull) dispatch_semaphore_t weakCacheLock; // a lock to keep the access to `weakCache` thread-safe
|
@property (nonatomic, strong, nonnull) dispatch_semaphore_t weakCacheLock; // a lock to keep the access to `weakCache` thread-safe
|
||||||
|
|
||||||
|
- (instancetype)init NS_UNAVAILABLE;
|
||||||
|
- (instancetype)initWithConfig:(nonnull SDImageCacheConfig *)config;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation SDMemoryCache
|
@implementation SDMemoryCache
|
||||||
|
@ -45,7 +49,7 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
||||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
|
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)init {
|
- (instancetype)initWithConfig:(SDImageCacheConfig *)config {
|
||||||
self = [super init];
|
self = [super init];
|
||||||
if (self) {
|
if (self) {
|
||||||
// Use a strong-weak maptable storing the secondary cache. Follow the doc that NSCache does not copy keys
|
// Use a strong-weak maptable storing the secondary cache. Follow the doc that NSCache does not copy keys
|
||||||
|
@ -53,6 +57,7 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
||||||
// At this case, we can sync weak cache back and do not need to load from disk cache
|
// At this case, we can sync weak cache back and do not need to load from disk cache
|
||||||
self.weakCache = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsStrongMemory valueOptions:NSPointerFunctionsWeakMemory capacity:0];
|
self.weakCache = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsStrongMemory valueOptions:NSPointerFunctionsWeakMemory capacity:0];
|
||||||
self.weakCacheLock = dispatch_semaphore_create(1);
|
self.weakCacheLock = dispatch_semaphore_create(1);
|
||||||
|
self.config = config;
|
||||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||||
selector:@selector(didReceiveMemoryWarning:)
|
selector:@selector(didReceiveMemoryWarning:)
|
||||||
name:UIApplicationDidReceiveMemoryWarningNotification
|
name:UIApplicationDidReceiveMemoryWarningNotification
|
||||||
|
@ -69,6 +74,9 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
||||||
// `setObject:forKey:` just call this with 0 cost. Override this is enough
|
// `setObject:forKey:` just call this with 0 cost. Override this is enough
|
||||||
- (void)setObject:(id)obj forKey:(id)key cost:(NSUInteger)g {
|
- (void)setObject:(id)obj forKey:(id)key cost:(NSUInteger)g {
|
||||||
[super setObject:obj forKey:key cost:g];
|
[super setObject:obj forKey:key cost:g];
|
||||||
|
if (!self.config.shouldUseWeakMemoryCache) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (key && obj) {
|
if (key && obj) {
|
||||||
// Store weak cache
|
// Store weak cache
|
||||||
LOCK(self.weakCacheLock);
|
LOCK(self.weakCacheLock);
|
||||||
|
@ -79,6 +87,9 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
||||||
|
|
||||||
- (id)objectForKey:(id)key {
|
- (id)objectForKey:(id)key {
|
||||||
id obj = [super objectForKey:key];
|
id obj = [super objectForKey:key];
|
||||||
|
if (!self.config.shouldUseWeakMemoryCache) {
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
if (key && !obj) {
|
if (key && !obj) {
|
||||||
// Check weak cache
|
// Check weak cache
|
||||||
LOCK(self.weakCacheLock);
|
LOCK(self.weakCacheLock);
|
||||||
|
@ -98,6 +109,9 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
||||||
|
|
||||||
- (void)removeObjectForKey:(id)key {
|
- (void)removeObjectForKey:(id)key {
|
||||||
[super removeObjectForKey:key];
|
[super removeObjectForKey:key];
|
||||||
|
if (!self.config.shouldUseWeakMemoryCache) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (key) {
|
if (key) {
|
||||||
// Remove weak cache
|
// Remove weak cache
|
||||||
LOCK(self.weakCacheLock);
|
LOCK(self.weakCacheLock);
|
||||||
|
@ -108,12 +122,22 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
||||||
|
|
||||||
- (void)removeAllObjects {
|
- (void)removeAllObjects {
|
||||||
[super removeAllObjects];
|
[super removeAllObjects];
|
||||||
|
if (!self.config.shouldUseWeakMemoryCache) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Manually remove should also remove weak cache
|
// Manually remove should also remove weak cache
|
||||||
LOCK(self.weakCacheLock);
|
LOCK(self.weakCacheLock);
|
||||||
[self.weakCache removeAllObjects];
|
[self.weakCache removeAllObjects];
|
||||||
UNLOCK(self.weakCacheLock);
|
UNLOCK(self.weakCacheLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
- (instancetype)initWithConfig:(SDImageCacheConfig *)config {
|
||||||
|
self = [super init];
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -163,7 +187,7 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
||||||
_config = [[SDImageCacheConfig alloc] init];
|
_config = [[SDImageCacheConfig alloc] init];
|
||||||
|
|
||||||
// Init the memory cache
|
// Init the memory cache
|
||||||
_memCache = [[SDMemoryCache alloc] init];
|
_memCache = [[SDMemoryCache alloc] initWithConfig:_config];
|
||||||
_memCache.name = fullNamespace;
|
_memCache.name = fullNamespace;
|
||||||
|
|
||||||
// Init the disk cache
|
// Init the disk cache
|
||||||
|
|
|
@ -29,15 +29,25 @@ typedef NS_ENUM(NSUInteger, SDImageCacheConfigExpireType) {
|
||||||
@property (assign, nonatomic) BOOL shouldDecompressImages;
|
@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;
|
@property (assign, nonatomic) BOOL shouldDisableiCloud;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* use memory cache [defaults to YES]
|
* Whether or not to use memory cache
|
||||||
|
* @note When the memory cache is disabled, the weak memory cache will also be disabled.
|
||||||
|
* Defaults to YES.
|
||||||
*/
|
*/
|
||||||
@property (assign, nonatomic) BOOL shouldCacheImagesInMemory;
|
@property (assign, nonatomic) BOOL shouldCacheImagesInMemory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The option to control weak memory cache for images. When enable, `SDImageCache`'s memory cache will use a weak maptable to store the image at the same time when it stored to memory, and get removed at the same time.
|
||||||
|
* However when memory warning triggered, since this weak maptable does not hold a strong reference to image instacnce, even when the memory cache itself is purged, some images which are held strongly by UIImageView or other instance can be recoveried again, to avoid re-query from disk cache or network. This may be helpful for case when app enter background and memory purched, cause cell flashing after re-enter foreground.
|
||||||
|
* Defautls to YES. You can change this option dynamically.
|
||||||
|
*/
|
||||||
|
@property (assign, nonatomic) BOOL shouldUseWeakMemoryCache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The reading options while reading cache from disk.
|
* The reading options while reading cache from disk.
|
||||||
* Defaults to 0. You can set this to `NSDataReadingMappedIfSafe` to improve performance.
|
* Defaults to 0. You can set this to `NSDataReadingMappedIfSafe` to improve performance.
|
||||||
|
|
|
@ -17,6 +17,7 @@ static const NSInteger kDefaultCacheMaxCacheAge = 60 * 60 * 24 * 7; // 1 week
|
||||||
_shouldDecompressImages = YES;
|
_shouldDecompressImages = YES;
|
||||||
_shouldDisableiCloud = YES;
|
_shouldDisableiCloud = YES;
|
||||||
_shouldCacheImagesInMemory = YES;
|
_shouldCacheImagesInMemory = YES;
|
||||||
|
_shouldUseWeakMemoryCache = YES;
|
||||||
_diskCacheReadingOptions = 0;
|
_diskCacheReadingOptions = 0;
|
||||||
_diskCacheWritingOptions = NSDataWritingAtomic;
|
_diskCacheWritingOptions = NSDataWritingAtomic;
|
||||||
_maxCacheAge = kDefaultCacheMaxCacheAge;
|
_maxCacheAge = kDefaultCacheMaxCacheAge;
|
||||||
|
|
Loading…
Reference in New Issue