PhotosCache.m 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. //
  2. // DDCacheManager.m
  3. // IOSDuoduo
  4. //
  5. // Created by 东邪 on 14-5-29.
  6. // Copyright (c) 2014年 dujia. All rights reserved.
  7. //
  8. #import "PhotosCache.h"
  9. #import "SDImageCache.h"
  10. #import "NSString+Additions.h"
  11. #import <CommonCrypto/CommonDigest.h>
  12. #import "DDSundriesCenter.h"
  13. @interface PhotosCache()
  14. @property (readonly, nonatomic) dispatch_queue_t ioQueue;
  15. @property(nonatomic,retain) NSFileManager *fileManager;
  16. @property (retain, nonatomic) NSCache *memCache;
  17. @end
  18. @implementation PhotosCache
  19. +(void)calculatePhotoSizeWithCompletionBlock:(void (^)(NSUInteger fileCount, NSUInteger totalSize))completionBlock
  20. {
  21. NSURL *diskCacheURL = [NSURL fileURLWithPath:PhotosMessageDir isDirectory:YES];
  22. [ [DDSundriesCenter instance] pushTaskToSerialQueue:^{
  23. NSUInteger fileCount = 0;
  24. NSUInteger totalSize = 0;
  25. NSFileManager *fileManager = [[NSFileManager alloc] init];
  26. NSDirectoryEnumerator *fileEnumerator = [fileManager enumeratorAtURL:diskCacheURL
  27. includingPropertiesForKeys:@[NSFileSize]
  28. options:NSDirectoryEnumerationSkipsHiddenFiles
  29. errorHandler:NULL];
  30. for (NSURL *fileURL in fileEnumerator) {
  31. NSNumber *fileSize;
  32. [fileURL getResourceValue:&fileSize forKey:NSURLFileSizeKey error:NULL];
  33. totalSize += [fileSize unsignedIntegerValue];
  34. fileCount += 1;
  35. }
  36. if (completionBlock) {
  37. dispatch_async(dispatch_get_main_queue(), ^{
  38. completionBlock(fileCount, totalSize);
  39. });
  40. }
  41. }];
  42. }
  43. -(NSData *)photoFromDiskCacheForKey:(NSString *)key
  44. {
  45. NSData *photoData = [self photoFromMemoryCacheForKey:key];
  46. if (photoData) {
  47. return photoData;
  48. }
  49. // Second check the disk cache...
  50. NSData *diskphotoData = [self diskPhotoForKey:key];
  51. if (diskphotoData) {
  52. [self.memCache setObject:diskphotoData forKey:key ];
  53. }
  54. return diskphotoData;
  55. }
  56. + (PhotosCache *)sharedPhotoCache
  57. {
  58. static dispatch_once_t once;
  59. static id instance;
  60. dispatch_once(&once, ^{
  61. instance = [self new];
  62. });
  63. return instance;
  64. }
  65. - (instancetype)init
  66. {
  67. self = [super init];
  68. if (self) {
  69. _ioQueue = dispatch_queue_create("com.mogujie.DDPhotosCache", DISPATCH_QUEUE_SERIAL);
  70. _memCache = [NSCache new];
  71. dispatch_sync(_ioQueue, ^{
  72. _fileManager = [NSFileManager new];
  73. });
  74. }
  75. return self;
  76. }
  77. - (void)storePhoto:(NSData *)data forKey:(NSString *)key
  78. {
  79. [self storePhoto:data forKey:key toDisk:YES];
  80. }
  81. - (void)removePhotoForKey:(NSString *)key
  82. {
  83. [self.memCache removeObjectForKey:key];
  84. dispatch_async(self.ioQueue, ^{
  85. [_fileManager removeItemAtPath:[self defaultCachePathForKey:key] error:nil];
  86. });
  87. }
  88. - (void)removePhotoFromNSCacheForKey:(NSString *)key
  89. {
  90. [self.memCache removeObjectForKey:key];
  91. }
  92. - (NSUInteger)getSize {
  93. __block NSUInteger size = 0;
  94. dispatch_sync(self.ioQueue, ^{
  95. NSDirectoryEnumerator *fileEnumerator = [_fileManager enumeratorAtPath:PhotosMessageDir];
  96. for (NSString *fileName in fileEnumerator) {
  97. NSString *filePath = [PhotosMessageDir stringByAppendingPathComponent:fileName];
  98. NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:nil];
  99. size += [attrs fileSize];
  100. }
  101. });
  102. return size;
  103. }
  104. - (int)getDiskCount {
  105. __block int count = 0;
  106. dispatch_sync(self.ioQueue, ^{
  107. NSDirectoryEnumerator *fileEnumerator = [_fileManager enumeratorAtPath:PhotosMessageDir];
  108. for (__unused NSString *fileName in fileEnumerator) {
  109. count += 1;
  110. }
  111. });
  112. return count;
  113. }
  114. - (void)storePhoto:(NSData *)photo forKey:(NSString *)key toDisk:(BOOL)toDisk {
  115. if (!photo || !key) {
  116. return;
  117. }
  118. [self.memCache setObject:photo forKey:key ];
  119. if (toDisk) {
  120. dispatch_async(self.ioQueue, ^{
  121. if (photo) {
  122. //如果图片存在 路径不存在 就创建一个路径
  123. if (![_fileManager fileExistsAtPath:PhotosMessageDir]) {
  124. [_fileManager createDirectoryAtPath:PhotosMessageDir withIntermediateDirectories:YES attributes:nil error:NULL];
  125. }
  126. //通过 key 创建一个文件路径 并将图片写入
  127. [_fileManager createFileAtPath:[self defaultCachePathForKey:key] contents:photo attributes:nil];
  128. }
  129. });
  130. }
  131. }
  132. - (NSString *)cachePathForKey:(NSString *)key inPath:(NSString *)path {
  133. NSString *filename = [self cachedFileNameForKey:key];
  134. return [path stringByAppendingPathComponent:filename];
  135. }
  136. - (NSString *)defaultCachePathForKey:(NSString *)key {
  137. return [self cachePathForKey:key inPath:PhotosMessageDir];
  138. }
  139. - (NSString *)cachedFileNameForKey:(NSString *)key {
  140. const char *str = [key UTF8String];
  141. if (str == NULL) {
  142. str = "";
  143. }
  144. unsigned char r[CC_MD5_DIGEST_LENGTH];
  145. CC_MD5(str, (CC_LONG)strlen(str), r);
  146. NSString *filename = [NSString stringWithFormat:@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
  147. r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9], r[10], r[11], r[12], r[13], r[14], r[15]];
  148. return filename;
  149. }
  150. - (NSOperation *)queryDiskCacheForKey:(NSString *)key done:(void (^)(NSData *photo))doneBlock {
  151. NSOperation *operation = [NSOperation new];
  152. if (!doneBlock) return nil;
  153. if (!key) {
  154. doneBlock(nil);
  155. return nil;
  156. }
  157. // First check the in-memory cache...
  158. NSData *photo = [self photoFromMemoryCacheForKey:key];
  159. if (photo) {
  160. doneBlock(photo);
  161. return nil;
  162. }
  163. dispatch_async(self.ioQueue, ^{
  164. if (operation.isCancelled) {
  165. return;
  166. }
  167. @autoreleasepool {
  168. NSData *diskPhotos = [self diskPhotoForKey:key];
  169. if (diskPhotos) {
  170. [self.memCache setObject:diskPhotos forKey:key];
  171. }
  172. dispatch_async(dispatch_get_main_queue(), ^{
  173. doneBlock(diskPhotos);
  174. });
  175. }
  176. });
  177. return operation;
  178. }
  179. - (NSData *)photoFromMemoryCacheForKey:(NSString *)key {
  180. return [self.memCache objectForKey:key];
  181. }
  182. - (NSData *)diskPhotoForKey:(NSString *)key {
  183. NSData *data = [self diskPhotosDataBySearchingAllPathsForKey:key];
  184. if (data) {
  185. return data;
  186. }
  187. else {
  188. return nil;
  189. }
  190. }
  191. - (NSData *)diskPhotosDataBySearchingAllPathsForKey:(NSString *)key {
  192. NSString *defaultPath = [self defaultCachePathForKey:key];
  193. NSData *data = [NSData dataWithContentsOfFile:defaultPath];
  194. if (data) {
  195. return data;
  196. }
  197. return nil;
  198. }
  199. -(NSString *)getKeyName
  200. {
  201. NSDateFormatter * formatter = [[NSDateFormatter alloc ] init];
  202. [formatter setDateFormat:@"YYYYMMddhhmmssSSS"];
  203. NSString *date = [formatter stringFromDate:[NSDate date]];
  204. NSString *timeLocal = [[NSString alloc] initWithFormat:@"%@", date];
  205. return [NSString stringWithFormat:@"%@_send",timeLocal];
  206. }
  207. -(NSMutableArray *)getAllImageCache
  208. {
  209. __block NSMutableArray *array = [NSMutableArray new];
  210. dispatch_sync(self.ioQueue, ^{
  211. NSDirectoryEnumerator *fileEnumerator = [_fileManager enumeratorAtPath:PhotosMessageDir];
  212. for (__unused NSString *fileName in fileEnumerator) {
  213. [array addObject:[NSString stringWithFormat:@"%@/%@",PhotosMessageDir,fileName]];
  214. }
  215. });
  216. return array;
  217. }
  218. -(void)clearAllCache
  219. {
  220. [self.memCache removeAllObjects];
  221. NSArray *allimage = [self getAllImageCache];
  222. [allimage enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
  223. NSString *path = (NSString *)obj;
  224. [_fileManager removeItemAtPath:path error:nil];
  225. }];
  226. }
  227. @end