diff --git a/SDWebImage/SDImageCache.h b/SDWebImage/SDImageCache.h index 97cc748..6fc571e 100644 --- a/SDWebImage/SDImageCache.h +++ b/SDWebImage/SDImageCache.h @@ -26,6 +26,8 @@ typedef NS_ENUM(NSInteger, SDImageCacheType) { typedef void(^SDWebImageQueryCompletedBlock)(UIImage *image, SDImageCacheType cacheType); +typedef void(^SDWebImageCheckCacheCompletionBlock)(BOOL isInCache); + /** * SDImageCache maintains a memory cache and an optional disk cache. Disk cache write operations are performed * asynchronous so it doesn’t add unnecessary latency to the UI. @@ -198,7 +200,20 @@ typedef void(^SDWebImageQueryCompletedBlock)(UIImage *image, SDImageCacheType ca - (void)calculateSizeWithCompletionBlock:(void (^)(NSUInteger fileCount, NSUInteger totalSize))completionBlock; /** - * Check if image exists in cache already + * Async 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. + * @note the completion block will be always executed on the main queue + */ +- (void)diskImageExistsWithKey:(NSString *)key completion:(SDWebImageCheckCacheCompletionBlock)completionBlock; + +/** + * Check if image exists in disk cache already (does not load the image) + * + * @param key the key describing the url + * + * @return YES if an image exists for the given key */ - (BOOL)diskImageExistsWithKey:(NSString *)key; diff --git a/SDWebImage/SDImageCache.m b/SDWebImage/SDImageCache.m index 396db09..85e4f9b 100644 --- a/SDWebImage/SDImageCache.m +++ b/SDWebImage/SDImageCache.m @@ -200,14 +200,26 @@ BOOL ImageDataHasPNGPreffix(NSData *data) { } - (BOOL)diskImageExistsWithKey:(NSString *)key { - __block BOOL exists = NO; - dispatch_sync(_ioQueue, ^{ - exists = [_fileManager fileExistsAtPath:[self defaultCachePathForKey:key]]; - }); - + BOOL exists = NO; + + // this is an exception to access the filemanager on another queue than ioQueue, but we are using the shared instance + // from apple docs on NSFileManager: The methods of the shared NSFileManager object can be called from multiple threads safely. + exists = [[NSFileManager defaultManager] fileExistsAtPath:[self defaultCachePathForKey:key]]; + return exists; } +- (void)diskImageExistsWithKey:(NSString *)key completion:(SDWebImageCheckCacheCompletionBlock)completionBlock { + dispatch_async(_ioQueue, ^{ + BOOL exists = [_fileManager fileExistsAtPath:[self defaultCachePathForKey:key]]; + if (completionBlock) { + dispatch_async(dispatch_get_main_queue(), ^{ + completionBlock(exists); + }); + } + }); +} + - (UIImage *)imageFromMemoryCacheForKey:(NSString *)key { return [self.memCache objectForKey:key]; } diff --git a/SDWebImage/SDWebImageManager.h b/SDWebImage/SDWebImageManager.h index 664b308..301787c 100644 --- a/SDWebImage/SDWebImageManager.h +++ b/SDWebImage/SDWebImageManager.h @@ -214,11 +214,46 @@ SDWebImageManager *manager = [SDWebImageManager sharedManager]; - (BOOL)isRunning; /** - * Check if image has already been cached + * Check if image has already been cached + * + * @param url image url + * + * @return if the image was already cached */ - (BOOL)cachedImageExistsForURL:(NSURL *)url; + +/** + * Check if image has already been cached on disk only + * + * @param url image url + * + * @return if the image was already cached (disk only) + */ - (BOOL)diskImageExistsForURL:(NSURL *)url; +/** + * Async check if image has already been cached + * + * @param url image url + * @param completionBlock the block to be executed when the check is finished + * + * @note the completion block is always executed on the main queue + */ +- (void)cachedImageExistsForURL:(NSURL *)url + completion:(SDWebImageCheckCacheCompletionBlock)completionBlock; + +/** + * Async check if image has already been cached on disk only + * + * @param url image url + * @param completionBlock the block to be executed when the check is finished + * + * @note the completion block is always executed on the main queue + */ +- (void)diskImageExistsForURL:(NSURL *)url + completion:(SDWebImageCheckCacheCompletionBlock)completionBlock; + + /** *Return the cache key for a given URL */ diff --git a/SDWebImage/SDWebImageManager.m b/SDWebImage/SDWebImageManager.m index f030a62..fd48529 100644 --- a/SDWebImage/SDWebImageManager.m +++ b/SDWebImage/SDWebImageManager.m @@ -71,6 +71,42 @@ return [self.imageCache diskImageExistsWithKey:key]; } +- (void)cachedImageExistsForURL:(NSURL *)url + completion:(SDWebImageCheckCacheCompletionBlock)completionBlock { + NSString *key = [self cacheKeyForURL:url]; + + BOOL isInMemoryCache = ([self.imageCache imageFromMemoryCacheForKey:key] != nil); + + if (isInMemoryCache) { + // making sure we call the completion block on the main queue + dispatch_async(dispatch_get_main_queue(), ^{ + if (completionBlock) { + completionBlock(YES); + } + }); + return; + } + + [self.imageCache diskImageExistsWithKey:key completion:^(BOOL isInDiskCache) { + // the completion block of checkDiskCacheForImageWithKey:completion: is always called on the main queue, no need to further dispatch + if (completionBlock) { + completionBlock(isInDiskCache); + } + }]; +} + +- (void)diskImageExistsForURL:(NSURL *)url + completion:(SDWebImageCheckCacheCompletionBlock)completionBlock { + NSString *key = [self cacheKeyForURL:url]; + + [self.imageCache diskImageExistsWithKey:key completion:^(BOOL isInDiskCache) { + // the completion block of checkDiskCacheForImageWithKey:completion: is always called on the main queue, no need to further dispatch + if (completionBlock) { + completionBlock(isInDiskCache); + } + }]; +} + - (id )downloadImageWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock