XHWebImageAutoSizeCache.m 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. //
  2. // XHWebImageAutoSizeCache.m
  3. // XHWebImageHeightLayoutExample
  4. //
  5. // Created by zhuxiaohui on 2016/11/16.
  6. // Copyright © 2016年 it7090.com. All rights reserved.
  7. // https://github.com/CoderZhuXH/XHWebImageAutoSize
  8. #import "XHWebImageAutoSizeCache.h"
  9. #import "NSString+XHWebImageAutoSize.h"
  10. #import "XHWebImageAutoSizeConst.h"
  11. @interface XHWebImageAutoSizeCache()
  12. @property(nonatomic,strong)NSCache * memCache;
  13. @property(nonnull,strong)NSFileManager *fileManager;
  14. @end
  15. @implementation XHWebImageAutoSizeCache
  16. +(XHWebImageAutoSizeCache *)shardCache{
  17. static XHWebImageAutoSizeCache *instance = nil;
  18. static dispatch_once_t oneToken;
  19. dispatch_once(&oneToken,^{
  20. instance = [[XHWebImageAutoSizeCache alloc] init];
  21. });
  22. return instance;
  23. }
  24. - (instancetype)init{
  25. self = [super init];
  26. if (self) {
  27. self.memCache = [[NSCache alloc] init];
  28. self.fileManager = [NSFileManager defaultManager];
  29. }
  30. return self;
  31. }
  32. -(BOOL)storeImageSize:(UIImage *)image forKey:(NSString *)key{
  33. if(!image || !key) return NO;
  34. CGSize imgSize = image.size;
  35. NSDictionary *sizeDict = @{@"width":@(imgSize.width),@"height":@(imgSize.height)};
  36. NSData *data = [self dataFromDict:sizeDict];
  37. NSString *keyName = key.sizeKeyName;
  38. [self.memCache setObject:data forKey:keyName];
  39. return [self.fileManager createFileAtPath:[self sizeCachePathForKey:keyName] contents:data attributes:nil];
  40. }
  41. -(void)storeImageSize:(UIImage *)image forKey:(NSString *)key completed:(XHWebImageAutoSizeCacheCompletionBlock)completedBlock{
  42. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  43. BOOL result = [self storeImageSize:image forKey:key];
  44. dispatch_async(dispatch_get_main_queue(), ^{
  45. if(completedBlock){
  46. completedBlock(result);
  47. }
  48. });
  49. });
  50. }
  51. -(BOOL)storeReloadState:(BOOL)state forKey:(NSString *)key{
  52. if(!key) return NO;
  53. NSString *stateString = @"0";
  54. if(state) stateString = @"1";
  55. NSDictionary *stateDict = @{@"reloadState":stateString};
  56. NSData *data = [self dataFromDict:stateDict];
  57. NSString *keyName = key.reloadKeyName;
  58. [self.memCache setObject:data forKey:keyName];
  59. return [self.fileManager createFileAtPath:[self reloadCachePathForKey:keyName] contents:data attributes:nil];
  60. }
  61. -(void)storeReloadState:(BOOL)state forKey:(NSString *)key completed:(XHWebImageAutoSizeCacheCompletionBlock)completedBlock{
  62. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  63. BOOL result = [self storeReloadState:state forKey:key];
  64. dispatch_async(dispatch_get_main_queue(), ^{
  65. if(completedBlock){
  66. completedBlock(result);
  67. }
  68. });
  69. });
  70. }
  71. -(CGSize)imageSizeFromCacheForKey:(NSString *)key{
  72. NSString *keyName = key.sizeKeyName;
  73. NSData *data = [self dataFromMemCacheForKey:keyName];
  74. if(!data){
  75. data = [self dataFromDiskCacheForKey:keyName isSizeCache:YES];
  76. }
  77. NSDictionary *sizeDict = [self dictFromData:data];
  78. CGFloat width = [sizeDict[@"width"] floatValue];
  79. CGFloat height = [sizeDict[@"height"] floatValue];
  80. CGSize size = CGSizeMake(width, height);
  81. return size;
  82. }
  83. -(BOOL)reloadStateFromCacheForKey:(NSString *)key{
  84. NSString *keyName = key.reloadKeyName;
  85. NSData *data = [self dataFromMemCacheForKey:keyName];
  86. if(!data){
  87. data = [self dataFromDiskCacheForKey:keyName isSizeCache:NO];
  88. }
  89. NSDictionary *reloadDict = [self dictFromData:data];
  90. NSInteger state = [reloadDict[@"reloadState"] integerValue];
  91. if(state ==1) return YES;
  92. return NO;
  93. }
  94. #pragma mark - XHWebImageAutoSizeCache (private)
  95. -(NSData *)dataFromMemCacheForKey:(NSString *)key{
  96. return [self.memCache objectForKey:key];
  97. }
  98. -(NSData *)dataFromDiskCacheForKey:(NSString *)key isSizeCache:(BOOL)isSizeCache{
  99. NSString *path = [self sizeCachePathForKey:key];
  100. if(!isSizeCache) path =[self reloadCachePathForKey:key];
  101. if ([self.fileManager fileExistsAtPath:path isDirectory:nil] == YES) {
  102. return [self.fileManager contentsAtPath:path];
  103. }
  104. return nil;
  105. }
  106. -(NSData *)dataFromDict:(NSDictionary *)dict{
  107. if(dict==nil) return nil;
  108. NSError *error;
  109. NSData *data =[NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:&error];
  110. if (error) {
  111. XHDebugLog(@"ERROR, faild to get json data");
  112. return nil;
  113. }
  114. return data;
  115. }
  116. -(NSDictionary *)dictFromData:(NSData *)data{
  117. if(data==nil) return nil;
  118. return [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
  119. }
  120. -(NSString *)sizeCachePathForKey:(NSString *)key{
  121. return [self cachePathForKey:key inPath:[self sizeCacheDirectory]];
  122. }
  123. -(NSString *)reloadCachePathForKey:(NSString *)key{
  124. return [self cachePathForKey:key inPath:[self reloadCacheDirectory]];
  125. }
  126. - (NSString *)cachePathForKey:(NSString *)key inPath:(NSString *)path {
  127. [self checkDirectory:path];
  128. return [path stringByAppendingPathComponent:key];
  129. }
  130. -(NSString *)sizeCacheDirectory{
  131. return [[self baseCacheDirectory] stringByAppendingPathComponent:@"SizeCache"];
  132. }
  133. -(NSString *)reloadCacheDirectory{
  134. return [[self baseCacheDirectory] stringByAppendingPathComponent:@"ReloadCache"];
  135. }
  136. -(NSString *)baseCacheDirectory{
  137. NSString *pathOfLibrary = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0];
  138. NSString *path = [pathOfLibrary stringByAppendingPathComponent:@"XHWebImageAutoSizeCache"];
  139. return path;
  140. }
  141. -(void)checkDirectory:(NSString *)path {
  142. BOOL isDir;
  143. if (![self.fileManager fileExistsAtPath:path isDirectory:&isDir]) {
  144. [self createBaseDirectoryAtPath:path];
  145. } else {
  146. if (!isDir) {
  147. NSError *error = nil;
  148. [self.fileManager removeItemAtPath:path error:&error];
  149. [self createBaseDirectoryAtPath:path];
  150. }
  151. }
  152. }
  153. - (void)createBaseDirectoryAtPath:(NSString *)path {
  154. __autoreleasing NSError *error = nil;
  155. [self.fileManager createDirectoryAtPath:path withIntermediateDirectories:YES
  156. attributes:nil error:&error];
  157. if (error) {
  158. XHDebugLog(@"create cache directory failed, error = %@", error);
  159. } else {
  160. [self addDoNotBackupAttribute:path];
  161. }
  162. }
  163. - (void)addDoNotBackupAttribute:(NSString *)path {
  164. NSURL *url = [NSURL fileURLWithPath:path];
  165. NSError *error = nil;
  166. [url setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:&error];
  167. if (error) {
  168. XHDebugLog(@"error to set do not backup attribute, error = %@", error);
  169. }
  170. }
  171. @end