Merge pull request #2379 from dreampiggy/feature_weak_cache_option
Add option to enable or disable weak memory cache for SDImageCache
This commit is contained in:
commit
f28796de62
|
@ -30,9 +30,13 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
|||
// Private
|
||||
@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) dispatch_semaphore_t weakCacheLock; // a lock to keep the access to `weakCache` thread-safe
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
- (instancetype)initWithConfig:(nonnull SDImageCacheConfig *)config;
|
||||
|
||||
@end
|
||||
|
||||
@implementation SDMemoryCache
|
||||
|
@ -45,7 +49,7 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
|||
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
- (instancetype)initWithConfig:(SDImageCacheConfig *)config {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
// 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
|
||||
self.weakCache = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsStrongMemory valueOptions:NSPointerFunctionsWeakMemory capacity:0];
|
||||
self.weakCacheLock = dispatch_semaphore_create(1);
|
||||
self.config = config;
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(didReceiveMemoryWarning:)
|
||||
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
|
||||
- (void)setObject:(id)obj forKey:(id)key cost:(NSUInteger)g {
|
||||
[super setObject:obj forKey:key cost:g];
|
||||
if (!self.config.shouldUseWeakMemoryCache) {
|
||||
return;
|
||||
}
|
||||
if (key && obj) {
|
||||
// Store weak cache
|
||||
LOCK(self.weakCacheLock);
|
||||
|
@ -79,6 +87,9 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
|||
|
||||
- (id)objectForKey:(id)key {
|
||||
id obj = [super objectForKey:key];
|
||||
if (!self.config.shouldUseWeakMemoryCache) {
|
||||
return obj;
|
||||
}
|
||||
if (key && !obj) {
|
||||
// Check weak cache
|
||||
LOCK(self.weakCacheLock);
|
||||
|
@ -98,6 +109,9 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
|||
|
||||
- (void)removeObjectForKey:(id)key {
|
||||
[super removeObjectForKey:key];
|
||||
if (!self.config.shouldUseWeakMemoryCache) {
|
||||
return;
|
||||
}
|
||||
if (key) {
|
||||
// Remove weak cache
|
||||
LOCK(self.weakCacheLock);
|
||||
|
@ -108,12 +122,22 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
|||
|
||||
- (void)removeAllObjects {
|
||||
[super removeAllObjects];
|
||||
if (!self.config.shouldUseWeakMemoryCache) {
|
||||
return;
|
||||
}
|
||||
// Manually remove should also remove weak cache
|
||||
LOCK(self.weakCacheLock);
|
||||
[self.weakCache removeAllObjects];
|
||||
UNLOCK(self.weakCacheLock);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
- (instancetype)initWithConfig:(SDImageCacheConfig *)config {
|
||||
self = [super init];
|
||||
return self;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
@ -163,7 +187,7 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
|||
_config = [[SDImageCacheConfig alloc] init];
|
||||
|
||||
// Init the memory cache
|
||||
_memCache = [[SDMemoryCache alloc] init];
|
||||
_memCache = [[SDMemoryCache alloc] initWithConfig:_config];
|
||||
_memCache.name = fullNamespace;
|
||||
|
||||
// Init the disk cache
|
||||
|
|
|
@ -29,15 +29,25 @@ typedef NS_ENUM(NSUInteger, SDImageCacheConfigExpireType) {
|
|||
@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
|
||||
* @note When the memory cache is disabled, the weak memory cache will also be disabled.
|
||||
* Defaults to YES.
|
||||
*/
|
||||
@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.
|
||||
* 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;
|
||||
_shouldDisableiCloud = YES;
|
||||
_shouldCacheImagesInMemory = YES;
|
||||
_shouldUseWeakMemoryCache = YES;
|
||||
_diskCacheReadingOptions = 0;
|
||||
_diskCacheWritingOptions = NSDataWritingAtomic;
|
||||
_maxCacheAge = kDefaultCacheMaxCacheAge;
|
||||
|
|
Loading…
Reference in New Issue