diff --git a/SDWebImage/SDImageCache.h b/SDWebImage/SDImageCache.h index 8989a184..2e1eed56 100644 --- a/SDWebImage/SDImageCache.h +++ b/SDWebImage/SDImageCache.h @@ -128,7 +128,7 @@ typedef void(^SDWebImageQueryCompletedBlock)(UIImage *image, SDImageCacheType ca - (void)removeImageForKey:(NSString *)key; /** - * Remove the image from memory and optionaly disk cache synchronously + * Remove the image from memory and optionally disk cache synchronously * * @param key The unique image cache key * @param fromDisk Also remove cache entry from disk if YES @@ -141,13 +141,26 @@ typedef void(^SDWebImageQueryCompletedBlock)(UIImage *image, SDImageCacheType ca - (void)clearMemory; /** - * Clear all disk cached images + * Clear all disk cached images. Non-blocking method - returns immediately. + * @param completionBlock An block that should be executed after cache expiration completes (optional) */ -- (void)clearDisk; - (void)clearDiskOnCompletion:(void (^)())completion; +/** + * Clear all disk cached images + * @see clearDiskOnCompletion: + */ +- (void)clearDisk; + +/** + * Remove all expired cached image from disk. Non-blocking method - returns immediately. + * @param completionBlock An block that should be executed after cache expiration completes (optional) + */ +- (void)cleanDiskWithCompletionBlock:(void (^)())completionBlock; + /** * Remove all expired cached image from disk + * @see cleanDiskWithCompletionBlock: */ - (void)cleanDisk; diff --git a/SDWebImage/SDImageCache.m b/SDWebImage/SDImageCache.m index 57778cf5..3f36e5e1 100644 --- a/SDWebImage/SDImageCache.m +++ b/SDWebImage/SDImageCache.m @@ -181,14 +181,11 @@ BOOL ImageDataHasPNGPreffix(NSData *data) { } if (data) { - // Can't use defaultManager another thread - NSFileManager *fileManager = [NSFileManager new]; - - if (![fileManager fileExistsAtPath:_diskCachePath]) { - [fileManager createDirectoryAtPath:_diskCachePath withIntermediateDirectories:YES attributes:nil error:NULL]; + if (![_fileManager fileExistsAtPath:_diskCachePath]) { + [_fileManager createDirectoryAtPath:_diskCachePath withIntermediateDirectories:YES attributes:nil error:NULL]; } - [fileManager createFileAtPath:[self defaultCachePathForKey:key] contents:data attributes:nil]; + [_fileManager createFileAtPath:[self defaultCachePathForKey:key] contents:data attributes:nil]; } }); } @@ -296,7 +293,7 @@ BOOL ImageDataHasPNGPreffix(NSData *data) { [self.memCache setObject:diskImage forKey:key cost:cost]; } - dispatch_main_sync_safe(^{ + dispatch_async(dispatch_get_main_queue(), ^{ doneBlock(diskImage, SDImageCacheTypeDisk); }); } @@ -318,7 +315,7 @@ BOOL ImageDataHasPNGPreffix(NSData *data) { if (fromDisk) { dispatch_async(self.ioQueue, ^{ - [[NSFileManager defaultManager] removeItemAtPath:[self defaultCachePathForKey:key] error:nil]; + [_fileManager removeItemAtPath:[self defaultCachePathForKey:key] error:nil]; }); } } @@ -342,14 +339,14 @@ BOOL ImageDataHasPNGPreffix(NSData *data) { - (void)clearDiskOnCompletion:(void (^)())completion { dispatch_async(self.ioQueue, ^{ - [[NSFileManager defaultManager] removeItemAtPath:self.diskCachePath error:nil]; - [[NSFileManager defaultManager] createDirectoryAtPath:self.diskCachePath - withIntermediateDirectories:YES - attributes:nil - error:NULL]; + [_fileManager removeItemAtPath:self.diskCachePath error:nil]; + [_fileManager createDirectoryAtPath:self.diskCachePath + withIntermediateDirectories:YES + attributes:nil + error:NULL]; if (completion) { - dispatch_main_sync_safe(^{ + dispatch_async(dispatch_get_main_queue(), ^{ completion(); }); } @@ -357,16 +354,19 @@ BOOL ImageDataHasPNGPreffix(NSData *data) { } - (void)cleanDisk { + [self cleanDiskWithCompletionBlock:nil]; +} + +- (void)cleanDiskWithCompletionBlock:(void (^)())completionBlock { dispatch_async(self.ioQueue, ^{ - NSFileManager *fileManager = [NSFileManager defaultManager]; NSURL *diskCacheURL = [NSURL fileURLWithPath:self.diskCachePath isDirectory:YES]; NSArray *resourceKeys = @[NSURLIsDirectoryKey, NSURLContentModificationDateKey, NSURLTotalFileAllocatedSizeKey]; // This enumerator prefetches useful properties for our cache files. - NSDirectoryEnumerator *fileEnumerator = [fileManager enumeratorAtURL:diskCacheURL - includingPropertiesForKeys:resourceKeys - options:NSDirectoryEnumerationSkipsHiddenFiles - errorHandler:NULL]; + NSDirectoryEnumerator *fileEnumerator = [_fileManager enumeratorAtURL:diskCacheURL + includingPropertiesForKeys:resourceKeys + options:NSDirectoryEnumerationSkipsHiddenFiles + errorHandler:NULL]; NSDate *expirationDate = [NSDate dateWithTimeIntervalSinceNow:-self.maxCacheAge]; NSMutableDictionary *cacheFiles = [NSMutableDictionary dictionary]; @@ -387,7 +387,7 @@ BOOL ImageDataHasPNGPreffix(NSData *data) { // Remove files that are older than the expiration date; NSDate *modificationDate = resourceValues[NSURLContentModificationDateKey]; if ([[modificationDate laterDate:expirationDate] isEqualToDate:expirationDate]) { - [fileManager removeItemAtURL:fileURL error:nil]; + [_fileManager removeItemAtURL:fileURL error:nil]; continue; } @@ -411,7 +411,7 @@ BOOL ImageDataHasPNGPreffix(NSData *data) { // Delete files until we fall below our desired cache size. for (NSURL *fileURL in sortedFiles) { - if ([fileManager removeItemAtURL:fileURL error:nil]) { + if ([_fileManager removeItemAtURL:fileURL error:nil]) { NSDictionary *resourceValues = cacheFiles[fileURL]; NSNumber *totalAllocatedSize = resourceValues[NSURLTotalFileAllocatedSizeKey]; currentCacheSize -= [totalAllocatedSize unsignedIntegerValue]; @@ -422,6 +422,11 @@ BOOL ImageDataHasPNGPreffix(NSData *data) { } } } + if (completionBlock) { + dispatch_async(dispatch_get_main_queue(), ^{ + completionBlock(); + }); + } }); } @@ -435,33 +440,33 @@ BOOL ImageDataHasPNGPreffix(NSData *data) { }]; // Start the long-running task and return immediately. - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - // Do the work associated with the task, preferably in chunks. - [self cleanDisk]; - + [self cleanDiskWithCompletionBlock:^{ [application endBackgroundTask:bgTask]; bgTask = UIBackgroundTaskInvalid; - }); + }]; } - (NSUInteger)getSize { - NSUInteger size = 0; - NSDirectoryEnumerator *fileEnumerator = [[NSFileManager defaultManager] enumeratorAtPath:self.diskCachePath]; - for (NSString *fileName in fileEnumerator) { - NSString *filePath = [self.diskCachePath stringByAppendingPathComponent:fileName]; - NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:nil]; - size += [attrs fileSize]; - } + __block NSUInteger size = 0; + dispatch_sync(self.ioQueue, ^{ + NSDirectoryEnumerator *fileEnumerator = [_fileManager enumeratorAtPath:self.diskCachePath]; + for (NSString *fileName in fileEnumerator) { + NSString *filePath = [self.diskCachePath stringByAppendingPathComponent:fileName]; + NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:nil]; + size += [attrs fileSize]; + } + }); return size; } - (int)getDiskCount { - int count = 0; - NSDirectoryEnumerator *fileEnumerator = [[NSFileManager defaultManager] enumeratorAtPath:self.diskCachePath]; - for (__unused NSString *fileName in fileEnumerator) { - count += 1; - } - + __block int count = 0; + dispatch_sync(self.ioQueue, ^{ + NSDirectoryEnumerator *fileEnumerator = [_fileManager enumeratorAtPath:self.diskCachePath]; + for (__unused NSString *fileName in fileEnumerator) { + count += 1; + } + }); return count; } @@ -472,11 +477,10 @@ BOOL ImageDataHasPNGPreffix(NSData *data) { NSUInteger fileCount = 0; NSUInteger totalSize = 0; - NSFileManager *fileManager = [NSFileManager defaultManager]; - NSDirectoryEnumerator *fileEnumerator = [fileManager enumeratorAtURL:diskCacheURL - includingPropertiesForKeys:@[NSFileSize] - options:NSDirectoryEnumerationSkipsHiddenFiles - errorHandler:NULL]; + NSDirectoryEnumerator *fileEnumerator = [_fileManager enumeratorAtURL:diskCacheURL + includingPropertiesForKeys:@[NSFileSize] + options:NSDirectoryEnumerationSkipsHiddenFiles + errorHandler:NULL]; for (NSURL *fileURL in fileEnumerator) { NSNumber *fileSize; @@ -486,7 +490,7 @@ BOOL ImageDataHasPNGPreffix(NSData *data) { } if (completionBlock) { - dispatch_main_sync_safe(^{ + dispatch_async(dispatch_get_main_queue(), ^{ completionBlock(fileCount, totalSize); }); }