Kache.m 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. //
  2. // Kache.m
  3. // KacheDemo
  4. //
  5. // Created by jiajun on 7/25/12.
  6. // Copyright (c) 2012 __MyCompanyName__. All rights reserved.
  7. //
  8. #define KACHE_DEFAULT_POOL_NAME @"kache_default_pool_name_LKJHGFDWQSFASRTYUIOP:"
  9. #define KACHE_DEFAULT_QUEUE_NAME @"kache_default_queue_name_QWEDFVHUIOPPLMUYTRDX:"
  10. #import "KConfig.h"
  11. #import "KHolder.h"
  12. #import "KPool.h"
  13. #import "KQueue.h"
  14. #import "Kache.h"
  15. @interface Kache ()
  16. @property (strong, nonatomic) KHolder *holder;
  17. @property (strong, nonatomic) NSMutableDictionary *pools;
  18. @property (strong, nonatomic) NSMutableDictionary *queues;
  19. @property (assign, nonatomic) BOOL loaded;
  20. @end
  21. @implementation Kache
  22. @synthesize filetoken = _filetoken;
  23. @synthesize holder = _holder;
  24. @synthesize pools = _pools;
  25. @synthesize queues = _queues;
  26. #pragma mark static for default
  27. + (Kache *)instance {
  28. static Kache *obj= nil;
  29. #if defined(__IPHONE_5_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_5_0
  30. static dispatch_once_t once_token;
  31. dispatch_once(&once_token, ^{
  32. obj = [[Kache alloc] initWithFiletoken:@""];
  33. });
  34. #elif defined(__IPHONE_4_3) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_3
  35. if (nil == obj) {
  36. obj = [[Kache alloc] initWithFiletoken:@""];
  37. }
  38. #else
  39. #error Your SDK is too old ! Need at least 4.3.
  40. #endif
  41. if (! obj.loaded) {
  42. [obj load];
  43. }
  44. return obj;
  45. }
  46. + (void)setValue:(id)value forKey:(NSString *)key expiredAfter:(NSInteger)duration {
  47. return [[Kache instance] setValue:value forKey:key expiredAfter:duration];
  48. }
  49. + (void)setValue:(id)value inDefaultPoolForKey:(NSString *)key expiredAfter:(NSInteger)duration {
  50. return [[Kache instance] setValue:value inPool:nil forKey:key expiredAfter:duration];
  51. }
  52. + (void)removeObjectForKey:(NSString *)key
  53. {
  54. return [[Kache instance] removeObjectForKey:key];
  55. }
  56. + (void)pushValue:(id)value {
  57. return [[Kache instance] pushValue:value toQueue:nil];
  58. }
  59. + (id)popValue {
  60. return [[Kache instance] popFromQueue:nil];
  61. }
  62. + (id)valueForKey:(NSString *)key {
  63. return [[Kache instance] valueForKey:key];
  64. }
  65. // Make sure the Pool exsists. Use newPoolWithName:size: to create a new Pool.
  66. + (void)setValue:(id)value inPool:(NSString *)name forKey:(NSString *)key expiredAfter:(NSInteger)duration {
  67. return [[Kache instance] setValue:value inPool:name forKey:key expiredAfter:duration];
  68. }
  69. // Make sure the Queue exsists. Use newQueueWithName:size: to create a new Queue.
  70. + (void)pushValue:(id)value toQueue:(NSString *)name {
  71. return [[Kache instance] pushValue:value toQueue:name];
  72. }
  73. + (id)popFromQueue:(NSString *)name {
  74. return [[Kache instance] popFromQueue:name];
  75. }
  76. + (void)newQueueWithName:(NSString *)name size:(NSInteger)size {
  77. return [[Kache instance] newQueueWithName:name size:size];
  78. }
  79. + (void)newPoolWithName:(NSString *)name size:(NSInteger)size {
  80. return [[Kache instance] newPoolWithName:name size:size];
  81. }
  82. + (void)save {
  83. return [[Kache instance] save];
  84. }
  85. + (void)load {
  86. // TODO load方法运行在iOS4.3上会挂
  87. // return [[Kache instance] load];
  88. }
  89. #pragma mark - init
  90. - (id)init
  91. {
  92. self = [super init];
  93. if (self) {
  94. self.queues = [[NSMutableDictionary alloc] init];
  95. self.pools = [[NSMutableDictionary alloc] init];
  96. self.holder = [[KHolder alloc] initWithToken:@""];
  97. [self newPoolWithName:nil size:0];
  98. [self newQueueWithName:nil size:0];
  99. self.filetoken = @"";
  100. return self;
  101. }
  102. return nil;
  103. }
  104. // Spcify a FileToken, Kache will save the data into a different place.
  105. - (id)initWithFiletoken:(NSString *)aFiletoken
  106. {
  107. self = [super init];
  108. if (self) {
  109. self.queues = [[NSMutableDictionary alloc] init];
  110. self.pools = [[NSMutableDictionary alloc] init];
  111. self.holder = [[KHolder alloc] initWithToken:aFiletoken];
  112. [self newPoolWithName:nil size:0];
  113. [self newQueueWithName:nil size:0];
  114. self.filetoken = aFiletoken;
  115. return self;
  116. }
  117. return nil;
  118. }
  119. #pragma mark - public
  120. - (void)setValue:(id)value forKey:(NSString *)key expiredAfter:(NSInteger)duration
  121. {
  122. [self.holder setValue:value forKey:key expiredAfter:duration];
  123. }
  124. // Make sure the Pool exsists. Use newPoolWithName:size: to create a new Pool.
  125. - (void)setValue:(id)value inPool:(NSString *)name forKey:(NSString *)key expiredAfter:(NSInteger)duration
  126. {
  127. if (nil == name || 0 >= [name length]) {
  128. name = KACHE_DEFAULT_POOL_NAME;
  129. }
  130. if ([[self.pools allKeys] containsObject:name]) {
  131. KPool *pool = [self.pools objectForKey:name];
  132. [pool setValue:value forKey:key expiredAfter:duration];
  133. }
  134. }
  135. - (void)removeObjectForKey:(NSString *)key
  136. {
  137. for (NSString *name in [self.pools allKeys]) {
  138. KPool *pool = [self.pools valueForKey:name];
  139. [pool removeObjectForKey:key];
  140. }
  141. [self.holder removeObjectForKey:key];
  142. }
  143. // Make sure the Queue exsists. Use newQueueWithName:size: to create a new Queue.
  144. - (void)pushValue:(id)value toQueue:(NSString *)name
  145. {
  146. if (nil == name || 0 >= [name length]) {
  147. name = KACHE_DEFAULT_QUEUE_NAME;
  148. }
  149. if ([[self.queues allKeys] containsObject:name]) {
  150. KQueue *queue = [self.queues objectForKey:name];
  151. [queue push:value];
  152. }
  153. }
  154. - (id)popFromQueue:(NSString *)name
  155. {
  156. if (nil == name || 0 >= [name length]) {
  157. name = KACHE_DEFAULT_QUEUE_NAME;
  158. }
  159. if ([[self.queues allKeys] containsObject:name]) {
  160. KQueue *queue = [self.queues objectForKey:name];
  161. return [queue pop];
  162. }
  163. return nil;
  164. }
  165. - (id)valueForKey:(NSString *)key
  166. {
  167. return [self.holder valueForKey:key];
  168. }
  169. - (void)newQueueWithName:(NSString *)name size:(NSInteger)size
  170. {
  171. if (nil == name || 0 >= [name length]) {
  172. name = KACHE_DEFAULT_QUEUE_NAME;
  173. }
  174. if (! [[self.queues allKeys] containsObject:name]) {
  175. KQueue *queue = [[KQueue alloc] initWithHolder:self.holder];
  176. if (0 < size) {
  177. queue.size = size;
  178. }
  179. queue.name = name;
  180. [self.queues setValue:queue
  181. forKey:name];
  182. }
  183. }
  184. - (void)newPoolWithName:(NSString *)name size:(NSInteger)size;
  185. {
  186. if (nil == name || 0 >= [name length]) {
  187. name = KACHE_DEFAULT_POOL_NAME;
  188. }
  189. if (! [[self.pools allKeys] containsObject:name]) {
  190. KPool *pool = [[KPool alloc] initWithHolder:self.holder];
  191. if (0 < size) {
  192. pool.size = size;
  193. }
  194. pool.name = name;
  195. [self.pools setValue:pool
  196. forKey:name];
  197. }
  198. }
  199. - (void)save {
  200. NSMutableArray *queueArray = [[NSMutableArray alloc] init];
  201. NSMutableArray *poolArray = [[NSMutableArray alloc] init];
  202. for (KQueue *queue in [self.queues objectEnumerator]) {
  203. [queueArray addObject:[queue serialize]];
  204. }
  205. for (KPool *pool in [self.pools objectEnumerator]) {
  206. [poolArray addObject:[pool serialize]];
  207. }
  208. NSDictionary *kacheDict = [[NSDictionary alloc] initWithObjectsAndKeys:
  209. [self.holder serialize], @"holder",
  210. queueArray, @"queues",
  211. poolArray, @"pools",
  212. nil];
  213. NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
  214. NSString *libDirectory = [paths objectAtIndex:0];
  215. NSString *path = @"KACHE_STORAGE_FILE_QERFCVBJKOL:";
  216. if (self.filetoken) {
  217. path = [path stringByAppendingPathExtension:self.filetoken];
  218. }
  219. NSString *filePath = [libDirectory stringByAppendingPathComponent:path];
  220. NSData *d = [NSKeyedArchiver archivedDataWithRootObject:kacheDict];
  221. [d writeToFile:filePath atomically:YES];
  222. }
  223. - (void)load {
  224. self.loaded = YES;
  225. NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
  226. NSString *libDirectory = [paths objectAtIndex:0];
  227. NSString *path = @"KACHE_STORAGE_FILE_QERFCVBJKOL:";
  228. if (self.filetoken) {
  229. path = [path stringByAppendingPathExtension:self.filetoken];
  230. }
  231. NSString *filePath = [libDirectory stringByAppendingPathComponent:path];
  232. NSData *d = [NSData dataWithContentsOfFile:filePath];
  233. if (d && 0 < d.length) {
  234. NSDictionary *kacheDict = [NSDictionary dictionaryWithDictionary:
  235. [NSKeyedUnarchiver unarchiveObjectWithData:d]];
  236. if (kacheDict && 0 < [kacheDict count]) {
  237. [self.holder unserializeFrom:[kacheDict objectForKey:@"holder"]];
  238. for (NSDictionary *queueDict in [kacheDict objectForKey:@"queues"]) {
  239. KQueue *queue = [[KQueue alloc] initWithHolder:self.holder];
  240. [queue unserializeFrom:queueDict];
  241. [self.queues setValue:queue forKey:[queueDict objectForKey:@"name"]];
  242. }
  243. for (NSDictionary *poolDict in [kacheDict objectForKey:@"pools"]) {
  244. KPool *pool = [[KPool alloc] initWithHolder:self.holder];
  245. [pool unserializeFrom:poolDict];
  246. [self.pools setValue:pool forKey:[poolDict objectForKey:@"name"]];
  247. }
  248. }
  249. }
  250. }
  251. @end