Merge branch 'master' of https://github.com/rs/SDWebImage into 5.x
* 'master' of https://github.com/rs/SDWebImage: Bumped version to 4.3.1 update CHANGELOG Create a subclass of NSCache using a weak cache. Only remove the cache when memory warning and sync back the alive instance from weak cache into cache. # Conflicts: # SDWebImage/SDImageCache.m
This commit is contained in:
commit
a54f41204d
32
CHANGELOG.md
32
CHANGELOG.md
|
@ -1,3 +1,29 @@
|
|||
## [4.3.1 - 4.3.0 Patch](https://github.com/rs/SDWebImage/releases/tag/4.3.1)
|
||||
See [all tickets marked for the 4.3.1 release](https://github.com/rs/SDWebImage/milestone/22)
|
||||
|
||||
#### Fixes
|
||||
- Cache
|
||||
- Fix that SDImageCacheQueryDataWhenInMemory should response cacheType to memory cache when the in-memory cache hit #2218
|
||||
- Project
|
||||
- Fix the macOS wrong minimum deployment target version to 10.9 #2206
|
||||
|
||||
#### Performances
|
||||
- Download Operation
|
||||
- Decode the image in the operation level's queue instead of URLSession delegate queue #2199
|
||||
|
||||
#### Improvements
|
||||
- Coder
|
||||
- Create a subclass of NSBitmapImageRep to fix the GIF frame duration issue on macOS #2223
|
||||
- View Category
|
||||
- Expose the read write to FLAnimatedImage associate to the UIImage to allow advanced feature like placeholder #2220
|
||||
- Cache
|
||||
- Create a subclass of NSCache using a weak cache #2228
|
||||
- Download Operation
|
||||
- Improvement download operation for priority and some protect #2208
|
||||
- Project
|
||||
- Fix CLANG\_WARN\_OBJC\_IMPLICIT\_RETAIN\_SELF warning #2225
|
||||
|
||||
|
||||
## [4.3.0 - Image Progress & Transition, on Jan 31th, 2018](https://github.com/rs/SDWebImage/releases/tag/4.3.0)
|
||||
See [all tickets marked for the 4.3.0 release](https://github.com/rs/SDWebImage/milestone/21)
|
||||
|
||||
|
@ -20,7 +46,7 @@ See [all tickets marked for the 4.3.0 release](https://github.com/rs/SDWebImage/
|
|||
- Cache
|
||||
- Fix the getSize method which use the default file manager instead of current file manager #2180
|
||||
- Manager
|
||||
- Fix the leak of runningOperations in race condition #2177 (Manager)
|
||||
- Fix the leak of runningOperations on race condition #2177
|
||||
- Downloader
|
||||
- Ensure all the session delegate completionHandler called and fix the leak when response error code below iOS 10 #2197
|
||||
- Fix dispatch_sync blocking the main queue on race condition #2184
|
||||
|
@ -31,9 +57,9 @@ See [all tickets marked for the 4.3.0 release](https://github.com/rs/SDWebImage/
|
|||
- Prefetcher
|
||||
- Fix the issue that prefetcher will cause stack overflow when the input urls list is huge because of recursion function call #2196
|
||||
|
||||
#### Performance
|
||||
#### Performances
|
||||
- View Category
|
||||
- Use the associate object to store the FLAnimatedImage into memory cache, avoid blinking or UIView transaction #2181
|
||||
- Use the associate object to store the FLAnimatedImage into memory cache, avoid blinking or UIView transition #2181
|
||||
|
||||
#### Improvements
|
||||
- Cache
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = 'SDWebImage'
|
||||
s.version = '4.3.0'
|
||||
s.version = '4.3.1'
|
||||
|
||||
s.osx.deployment_target = '10.10'
|
||||
s.ios.deployment_target = '8.0'
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
#import "NSImage+Additions.h"
|
||||
#import "SDWebImageCodersManager.h"
|
||||
|
||||
#define LOCK(lock) dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER);
|
||||
#define UNLOCK(lock) dispatch_semaphore_signal(lock);
|
||||
|
||||
static void * SDImageCacheContext = &SDImageCacheContext;
|
||||
|
||||
FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
||||
|
@ -21,10 +24,106 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
|||
#endif
|
||||
}
|
||||
|
||||
// A memory cache which auto purge the cache on memory warning and support weak cache.
|
||||
@interface SDMemoryCache <KeyType, ObjectType> : NSCache <KeyType, ObjectType>
|
||||
|
||||
@end
|
||||
|
||||
// Private
|
||||
@interface SDMemoryCache <KeyType, ObjectType> ()
|
||||
|
||||
@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
|
||||
|
||||
@end
|
||||
|
||||
@implementation SDMemoryCache
|
||||
|
||||
// Current this seems no use on macOS (macOS use virtual memory and do not clear cache when memory warning). So we only override on iOS/tvOS platform.
|
||||
// But in the future there may be more options and features for this subclass.
|
||||
#if SD_UIKIT
|
||||
|
||||
- (void)dealloc {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
// Use a strong-weak maptable storing the secondary cache. Follow the doc that NSCache does not copy keys
|
||||
// This is useful when the memory warning, the cache was purged. However, the image instance can be retained by other instance such as imageViews and alive.
|
||||
// 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);
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(didReceiveMemoryWarning:)
|
||||
name:UIApplicationDidReceiveMemoryWarningNotification
|
||||
object:nil];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning:(NSNotification *)notification {
|
||||
// Only remove cache, but keep weak cache
|
||||
[super removeAllObjects];
|
||||
}
|
||||
|
||||
// `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 (key && obj) {
|
||||
// Store weak cache
|
||||
LOCK(self.weakCacheLock);
|
||||
[self.weakCache setObject:obj forKey:key];
|
||||
UNLOCK(self.weakCacheLock);
|
||||
}
|
||||
}
|
||||
|
||||
- (id)objectForKey:(id)key {
|
||||
id obj = [super objectForKey:key];
|
||||
if (key && !obj) {
|
||||
// Check weak cache
|
||||
LOCK(self.weakCacheLock);
|
||||
obj = [self.weakCache objectForKey:key];
|
||||
UNLOCK(self.weakCacheLock);
|
||||
if (obj) {
|
||||
// Sync cache
|
||||
NSUInteger cost = 0;
|
||||
if ([obj isKindOfClass:[UIImage class]]) {
|
||||
cost = SDCacheCostForImage(obj);
|
||||
}
|
||||
[super setObject:obj forKey:key cost:cost];
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
- (void)removeObjectForKey:(id)key {
|
||||
[super removeObjectForKey:key];
|
||||
if (key) {
|
||||
// Remove weak cache
|
||||
LOCK(self.weakCacheLock);
|
||||
[self.weakCache removeObjectForKey:key];
|
||||
UNLOCK(self.weakCacheLock);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)removeAllObjects {
|
||||
[super removeAllObjects];
|
||||
// Manually remove should also remove weak cache
|
||||
LOCK(self.weakCacheLock);
|
||||
[self.weakCache removeAllObjects];
|
||||
UNLOCK(self.weakCacheLock);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
@interface SDImageCache ()
|
||||
|
||||
#pragma mark - Properties
|
||||
@property (strong, nonatomic, nonnull) NSCache *memCache;
|
||||
@property (strong, nonatomic, nonnull) SDMemoryCache *memCache;
|
||||
@property (strong, nonatomic, nonnull) NSString *diskCachePath;
|
||||
@property (strong, nonatomic, nullable) NSMutableArray<NSString *> *customPaths;
|
||||
@property (strong, nonatomic, nullable) dispatch_queue_t ioQueue;
|
||||
|
@ -75,7 +174,7 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
|||
[_config addObserver:self forKeyPath:NSStringFromSelector(@selector(maxMemoryCount)) options:0 context:SDImageCacheContext];
|
||||
|
||||
// Init the memory cache
|
||||
_memCache = [[NSCache alloc] init];
|
||||
_memCache = [[SDMemoryCache alloc] init];
|
||||
_memCache.name = fullNamespace;
|
||||
|
||||
// Init the disk cache
|
||||
|
@ -92,11 +191,6 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
|||
|
||||
#if SD_UIKIT
|
||||
// Subscribe to app events
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(clearMemory)
|
||||
name:UIApplicationDidReceiveMemoryWarningNotification
|
||||
object:nil];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(deleteOldFiles)
|
||||
name:UIApplicationWillTerminateNotification
|
||||
|
|
|
@ -26,7 +26,7 @@ typedef NSMapTable<NSString *, id<SDWebImageOperation>> SDOperationsDictionary;
|
|||
if (operations) {
|
||||
return operations;
|
||||
}
|
||||
operations = [[NSMapTable alloc] initWithKeyOptions:NSMapTableCopyIn valueOptions:NSMapTableWeakMemory capacity:0];
|
||||
operations = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsStrongMemory valueOptions:NSPointerFunctionsWeakMemory capacity:0];
|
||||
objc_setAssociatedObject(self, &loadOperationKey, operations, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
return operations;
|
||||
}
|
||||
|
|
|
@ -15,11 +15,11 @@
|
|||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>4.3.0</string>
|
||||
<string>4.3.1</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>4.3.0</string>
|
||||
<string>4.3.1</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string></string>
|
||||
</dict>
|
||||
|
|
Loading…
Reference in New Issue