From b1203d4a9e4ba69e1b0da90e009517fa0734c67a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=A2=E5=85=8B?= Date: Fri, 23 May 2014 17:44:59 +0800 Subject: [PATCH] It's generally a bad idea to remove items from a container while iterating through it. And fix the thread safe issue. --- SDWebImage/SDImageCache.m | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/SDWebImage/SDImageCache.m b/SDWebImage/SDImageCache.m index 3f36e5e..233fd5a 100644 --- a/SDWebImage/SDImageCache.m +++ b/SDWebImage/SDImageCache.m @@ -358,7 +358,7 @@ BOOL ImageDataHasPNGPreffix(NSData *data) { } - (void)cleanDiskWithCompletionBlock:(void (^)())completionBlock { - dispatch_async(self.ioQueue, ^{ + dispatch_barrier_async(self.ioQueue, ^{ NSURL *diskCacheURL = [NSURL fileURLWithPath:self.diskCachePath isDirectory:YES]; NSArray *resourceKeys = @[NSURLIsDirectoryKey, NSURLContentModificationDateKey, NSURLTotalFileAllocatedSizeKey]; @@ -376,6 +376,7 @@ BOOL ImageDataHasPNGPreffix(NSData *data) { // // 1. Removing files that are older than the expiration date. // 2. Storing file attributes for the size-based cleanup pass. + NSMutableArray *urlsToDelete = [[NSMutableArray alloc] init]; for (NSURL *fileURL in fileEnumerator) { NSDictionary *resourceValues = [fileURL resourceValuesForKeys:resourceKeys error:NULL]; @@ -387,7 +388,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]; + [urlsToDelete addObject:fileURL]; continue; } @@ -396,6 +397,10 @@ BOOL ImageDataHasPNGPreffix(NSData *data) { currentCacheSize += [totalAllocatedSize unsignedIntegerValue]; [cacheFiles setObject:resourceValues forKey:fileURL]; } + + for (NSURL *fileURL in urlsToDelete) { + [_fileManager removeItemAtURL:fileURL error:nil]; + } // If our remaining disk cache exceeds a configured maximum size, perform a second // size-based cleanup pass. We delete the oldest files first.