Merge pull request #2190 from dreampiggy/fix_check_io_queue

Add sync version API diskImageDataExistsWithKey and keep thread-safe. Add diskCacheWritingOptions
This commit is contained in:
DreamPiggy 2018-01-26 18:34:52 +08:00 committed by GitHub
commit f2d9abbc4a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 57 additions and 22 deletions

View File

@ -171,6 +171,13 @@ typedef void(^SDWebImageCalculateSizeBlock)(NSUInteger fileCount, NSUInteger tot
*/ */
- (void)diskImageExistsWithKey:(nullable NSString *)key completion:(nullable SDWebImageCheckCacheCompletionBlock)completionBlock; - (void)diskImageExistsWithKey:(nullable NSString *)key completion:(nullable SDWebImageCheckCacheCompletionBlock)completionBlock;
/**
* Sync 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;
/** /**
* Operation that queries the cache asynchronously and call the completion when done. * Operation that queries the cache asynchronously and call the completion when done.
* *

View File

@ -106,14 +106,6 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
[[NSNotificationCenter defaultCenter] removeObserver:self]; [[NSNotificationCenter defaultCenter] removeObserver:self];
} }
- (void)checkIfQueueIsIOQueue {
const char *currentQueueLabel = dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL);
const char *ioQueueLabel = dispatch_queue_get_label(self.ioQueue);
if (strcmp(currentQueueLabel, ioQueueLabel) != 0) {
NSLog(@"This method should be called from the ioQueue");
}
}
#pragma mark - Cache paths #pragma mark - Cache paths
- (void)addReadOnlyCachePath:(nonnull NSString *)path { - (void)addReadOnlyCachePath:(nonnull NSString *)path {
@ -201,7 +193,7 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
} }
data = [[SDWebImageCodersManager sharedInstance] encodedDataWithImage:image format:format]; data = [[SDWebImageCodersManager sharedInstance] encodedDataWithImage:image format:format];
} }
[self storeImageDataToDisk:data forKey:key]; [self _storeImageDataToDisk:data forKey:key];
} }
if (completionBlock) { if (completionBlock) {
@ -221,8 +213,16 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
if (!imageData || !key) { if (!imageData || !key) {
return; return;
} }
dispatch_sync(self.ioQueue, ^{
[self _storeImageDataToDisk:imageData forKey:key];
});
}
[self checkIfQueueIsIOQueue]; // Make sure to call form io queue by caller
- (void)_storeImageDataToDisk:(nullable NSData *)imageData forKey:(nullable NSString *)key {
if (!imageData || !key) {
return;
}
if (![_fileManager fileExistsAtPath:_diskCachePath]) { if (![_fileManager fileExistsAtPath:_diskCachePath]) {
[_fileManager createDirectoryAtPath:_diskCachePath withIntermediateDirectories:YES attributes:nil error:NULL]; [_fileManager createDirectoryAtPath:_diskCachePath withIntermediateDirectories:YES attributes:nil error:NULL];
@ -233,7 +233,7 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
// transform to NSUrl // transform to NSUrl
NSURL *fileURL = [NSURL fileURLWithPath:cachePathForKey]; NSURL *fileURL = [NSURL fileURLWithPath:cachePathForKey];
[_fileManager createFileAtPath:cachePathForKey contents:imageData attributes:nil]; [imageData writeToURL:fileURL options:self.config.diskCacheWritingOptions error:nil];
// disable iCloud backup // disable iCloud backup
if (self.config.shouldDisableiCloud) { if (self.config.shouldDisableiCloud) {
@ -244,7 +244,33 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
#pragma mark - Query and Retrieve Ops #pragma mark - Query and Retrieve Ops
- (void)diskImageExistsWithKey:(nullable NSString *)key completion:(nullable SDWebImageCheckCacheCompletionBlock)completionBlock { - (void)diskImageExistsWithKey:(nullable NSString *)key completion:(nullable SDWebImageCheckCacheCompletionBlock)completionBlock {
dispatch_async(_ioQueue, ^{ dispatch_async(self.ioQueue, ^{
BOOL exists = [self _diskImageDataExistsWithKey:key];
if (completionBlock) {
dispatch_async(dispatch_get_main_queue(), ^{
completionBlock(exists);
});
}
});
}
- (BOOL)diskImageDataExistsWithKey:(nullable NSString *)key {
if (!key) {
return NO;
}
__block BOOL exists = NO;
dispatch_sync(self.ioQueue, ^{
exists = [self _diskImageDataExistsWithKey:key];
});
return exists;
}
// Make sure to call form io queue by caller
- (BOOL)_diskImageDataExistsWithKey:(nullable NSString *)key {
if (!key) {
return NO;
}
BOOL exists = [_fileManager fileExistsAtPath:[self defaultCachePathForKey:key]]; 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 // fallback because of https://github.com/rs/SDWebImage/pull/976 that added the extension to the disk file name
@ -253,12 +279,7 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
exists = [_fileManager fileExistsAtPath:[self defaultCachePathForKey:key].stringByDeletingPathExtension]; exists = [_fileManager fileExistsAtPath:[self defaultCachePathForKey:key].stringByDeletingPathExtension];
} }
if (completionBlock) { return exists;
dispatch_async(dispatch_get_main_queue(), ^{
completionBlock(exists);
});
}
});
} }
- (nullable UIImage *)imageFromMemoryCacheForKey:(nullable NSString *)key { - (nullable UIImage *)imageFromMemoryCacheForKey:(nullable NSString *)key {

View File

@ -29,10 +29,16 @@
/** /**
* The reading options while reading cache from disk. * The reading options while reading cache from disk.
* Defaults to 0. You can set this to mapped file to improve performance. * Defaults to 0. You can set this to `NSDataReadingMappedIfSafe` to improve performance.
*/ */
@property (assign, nonatomic) NSDataReadingOptions diskCacheReadingOptions; @property (assign, nonatomic) NSDataReadingOptions diskCacheReadingOptions;
/**
* The writing options while writing cache to disk.
* Defaults to `NSDataWritingAtomic`. You can set this to `NSDataWritingWithoutOverwriting` to prevent overwriting an existing file.
*/
@property (assign, nonatomic) NSDataWritingOptions diskCacheWritingOptions;
/** /**
* The maximum length of time to keep an image in the cache, in seconds. * The maximum length of time to keep an image in the cache, in seconds.
*/ */

View File

@ -18,6 +18,7 @@ static const NSInteger kDefaultCacheMaxCacheAge = 60 * 60 * 24 * 7; // 1 week
_shouldDisableiCloud = YES; _shouldDisableiCloud = YES;
_shouldCacheImagesInMemory = YES; _shouldCacheImagesInMemory = YES;
_diskCacheReadingOptions = 0; _diskCacheReadingOptions = 0;
_diskCacheWritingOptions = NSDataWritingAtomic;
_maxCacheAge = kDefaultCacheMaxCacheAge; _maxCacheAge = kDefaultCacheMaxCacheAge;
_maxCacheSize = 0; _maxCacheSize = 0;
} }