No Description

AWSTMDiskCache.h 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. /**
  2. `TMDiskCache` is a thread safe key/value store backed by the file system. It accepts any object conforming
  3. to the `NSCoding` protocol, which includes the basic Foundation data types and collection classes and also
  4. many UIKit classes, notably `UIImage`. All work is performed on a serial queue shared by all instances in
  5. the app, and archiving is handled by `NSKeyedArchiver`. This is a particular advantage for `UIImage` because
  6. it skips `UIImagePNGRepresentation()` and retains information like scale and orientation.
  7. The designated initializer for `TMDiskCache` is <initWithName:>. The <name> string is used to create a directory
  8. under Library/Caches that scopes disk access for any instance sharing this name. Multiple instances with the
  9. same name are allowed because all disk access is serialized on the <sharedQueue>. The <name> also appears in
  10. stack traces and return value for `description:`.
  11. Unless otherwise noted, all properties and methods are safe to access from any thread at any time. All blocks
  12. will cause the queue to wait, making it safe to access and manipulate the actual cache files on disk for the
  13. duration of the block. In addition, the <sharedQueue> can be set to target an existing serial I/O queue, should
  14. your app already have one.
  15. Because this cache is bound by disk I/O it can be much slower than <TMMemoryCache>, although values stored in
  16. `TMDiskCache` persist after application relaunch. Using <TMCache> is recommended over using `TMDiskCache`
  17. by itself, as it adds a fast layer of additional memory caching while still writing to disk.
  18. All access to the cache is dated so the that the least-used objects can be trimmed first. Setting an optional
  19. <ageLimit> will trigger a GCD timer to periodically to trim the cache with <trimToDate:>.
  20. */
  21. #import <Foundation/Foundation.h>
  22. @class AWSTMDiskCache;
  23. @protocol AWSTMCacheBackgroundTaskManager;
  24. typedef void (^AWSTMDiskCacheBlock)(AWSTMDiskCache *cache);
  25. typedef void (^AWSTMDiskCacheObjectBlock)(AWSTMDiskCache *cache, NSString *key, id <NSCoding> object, NSURL *fileURL);
  26. @interface AWSTMDiskCache : NSObject
  27. #pragma mark -
  28. /// @name Core
  29. /**
  30. The name of this cache, used to create a directory under Library/Caches and also appearing in stack traces.
  31. */
  32. @property (readonly) NSString *name;
  33. /**
  34. The URL of the directory used by this cache, usually `Library/Caches/com.tumblr.TMDiskCache.(name)`
  35. @warning Do not interact with files under this URL except on the <sharedQueue>.
  36. */
  37. @property (readonly) NSURL *cacheURL;
  38. /**
  39. The total number of bytes used on disk, as reported by `NSURLTotalFileAllocatedSizeKey`.
  40. @warning This property is technically safe to access from any thread, but it reflects the value *right now*,
  41. not taking into account any pending operations. In most cases this value should only be read from a block on the
  42. <sharedQueue>, which will ensure its accuracy and prevent it from changing during the lifetime of the block.
  43. For example:
  44. // some background thread, not a block already running on the shared queue
  45. dispatch_sync([TMDiskCache sharedQueue], ^{
  46. NSLog(@"accurate, unchanging byte count: %d", [[TMDiskCache sharedCache] byteCount]);
  47. });
  48. */
  49. @property (readonly) NSUInteger byteCount;
  50. /**
  51. The maximum number of bytes allowed on disk. This value is checked every time an object is set, if the written
  52. size exceeds the limit a trim call is queued. Defaults to `0.0`, meaning no practical limit.
  53. @warning Do not read this property on the <sharedQueue> (including asynchronous method blocks).
  54. */
  55. @property (assign) NSUInteger byteLimit;
  56. /**
  57. The maximum number of seconds an object is allowed to exist in the cache. Setting this to a value
  58. greater than `0.0` will start a recurring GCD timer with the same period that calls <trimToDate:>.
  59. Setting it back to `0.0` will stop the timer. Defaults to `0.0`, meaning no limit.
  60. @warning Do not read this property on the <sharedQueue> (including asynchronous method blocks).
  61. */
  62. @property (assign) NSTimeInterval ageLimit;
  63. #pragma mark -
  64. /// @name Event Blocks
  65. /**
  66. A block to be executed just before an object is added to the cache. The queue waits during execution.
  67. */
  68. @property (copy) AWSTMDiskCacheObjectBlock willAddObjectBlock;
  69. /**
  70. A block to be executed just before an object is removed from the cache. The queue waits during execution.
  71. */
  72. @property (copy) AWSTMDiskCacheObjectBlock willRemoveObjectBlock;
  73. /**
  74. A block to be executed just before all objects are removed from the cache as a result of <removeAllObjects:>.
  75. The queue waits during execution.
  76. */
  77. @property (copy) AWSTMDiskCacheBlock willRemoveAllObjectsBlock;
  78. /**
  79. A block to be executed just after an object is added to the cache. The queue waits during execution.
  80. */
  81. @property (copy) AWSTMDiskCacheObjectBlock didAddObjectBlock;
  82. /**
  83. A block to be executed just after an object is removed from the cache. The queue waits during execution.
  84. */
  85. @property (copy) AWSTMDiskCacheObjectBlock didRemoveObjectBlock;
  86. /**
  87. A block to be executed just after all objects are removed from the cache as a result of <removeAllObjects:>.
  88. The queue waits during execution.
  89. */
  90. @property (copy) AWSTMDiskCacheBlock didRemoveAllObjectsBlock;
  91. #pragma mark -
  92. /// @name Initialization
  93. /**
  94. A shared cache.
  95. @result The shared singleton cache instance.
  96. */
  97. + (instancetype)sharedCache;
  98. /**
  99. A shared serial queue, used by all instances of this class. Use `dispatch_set_target_queue` to integrate
  100. this queue with an exisiting serial I/O queue.
  101. @result The shared singleton queue instance.
  102. */
  103. + (dispatch_queue_t)sharedQueue;
  104. /**
  105. Empties the trash with `DISPATCH_QUEUE_PRIORITY_BACKGROUND`. Does not block the <sharedQueue>.
  106. */
  107. + (void)emptyTrash;
  108. /**
  109. Multiple instances with the same name are allowed and can safely access
  110. the same data on disk thanks to the magic of seriality.
  111. @see name
  112. @param name The name of the cache.
  113. @result A new cache with the specified name.
  114. */
  115. - (instancetype)initWithName:(NSString *)name;
  116. /**
  117. The designated initializer. Multiple instances with the same name are allowed and can safely access
  118. the same data on disk thanks to the magic of seriality.
  119. @see name
  120. @param name The name of the cache.
  121. @param rootPath The path of the cache.
  122. @result A new cache with the specified name.
  123. */
  124. - (instancetype)initWithName:(NSString *)name rootPath:(NSString *)rootPath;
  125. #pragma mark -
  126. /// @name Asynchronous Methods
  127. /**
  128. Retrieves the object for the specified key. This method returns immediately and executes the passed
  129. block as soon as the object is available on the serial <sharedQueue>.
  130. @warning The fileURL is only valid for the duration of this block, do not use it after the block ends.
  131. @param key The key associated with the requested object.
  132. @param block A block to be executed serially when the object is available.
  133. */
  134. - (void)objectForKey:(NSString *)key block:(AWSTMDiskCacheObjectBlock)block;
  135. /**
  136. Retrieves the fileURL for the specified key without actually reading the data from disk. This method
  137. returns immediately and executes the passed block as soon as the object is available on the serial
  138. <sharedQueue>.
  139. @warning Access is protected for the duration of the block, but to maintain safe disk access do not
  140. access this fileURL after the block has ended. Do all work on the <sharedQueue>.
  141. @param key The key associated with the requested object.
  142. @param block A block to be executed serially when the file URL is available.
  143. */
  144. - (void)fileURLForKey:(NSString *)key block:(AWSTMDiskCacheObjectBlock)block;
  145. /**
  146. Stores an object in the cache for the specified key. This method returns immediately and executes the
  147. passed block as soon as the object has been stored.
  148. @param object An object to store in the cache.
  149. @param key A key to associate with the object. This string will be copied.
  150. @param block A block to be executed serially after the object has been stored, or nil.
  151. */
  152. - (void)setObject:(id <NSCoding>)object forKey:(NSString *)key block:(AWSTMDiskCacheObjectBlock)block;
  153. /**
  154. Removes the object for the specified key. This method returns immediately and executes the passed block
  155. as soon as the object has been removed.
  156. @param key The key associated with the object to be removed.
  157. @param block A block to be executed serially after the object has been removed, or nil.
  158. */
  159. - (void)removeObjectForKey:(NSString *)key block:(AWSTMDiskCacheObjectBlock)block;
  160. /**
  161. Removes all objects from the cache that have not been used since the specified date.
  162. This method returns immediately and executes the passed block as soon as the cache has been trimmed.
  163. @param date Objects that haven't been accessed since this date are removed from the cache.
  164. @param block A block to be executed serially after the cache has been trimmed, or nil.
  165. */
  166. - (void)trimToDate:(NSDate *)date block:(AWSTMDiskCacheBlock)block;
  167. /**
  168. Removes objects from the cache, largest first, until the cache is equal to or smaller than the specified byteCount.
  169. This method returns immediately and executes the passed block as soon as the cache has been trimmed.
  170. @param byteCount The cache will be trimmed equal to or smaller than this size.
  171. @param block A block to be executed serially after the cache has been trimmed, or nil.
  172. */
  173. - (void)trimToSize:(NSUInteger)byteCount block:(AWSTMDiskCacheBlock)block;
  174. /**
  175. Removes objects from the cache, ordered by date (least recently used first), until the cache is equal to or smaller
  176. than the specified byteCount. This method returns immediately and executes the passed block as soon as the cache has
  177. been trimmed.
  178. @param byteCount The cache will be trimmed equal to or smaller than this size.
  179. @param block A block to be executed serially after the cache has been trimmed, or nil.
  180. */
  181. - (void)trimToSizeByDate:(NSUInteger)byteCount block:(AWSTMDiskCacheBlock)block;
  182. /**
  183. Removes all objects from the cache. This method returns immediately and executes the passed block as soon as the
  184. cache has been cleared.
  185. @param block A block to be executed serially after the cache has been cleared, or nil.
  186. */
  187. - (void)removeAllObjects:(AWSTMDiskCacheBlock)block;
  188. /**
  189. Loops through all objects in the cache (reads and writes are suspended during the enumeration). Data is not actually
  190. read from disk, the `object` parameter of the block will be `nil` but the `fileURL` will be available.
  191. This method returns immediately.
  192. @param block A block to be executed for every object in the cache.
  193. @param completionBlock An optional block to be executed after the enumeration is complete.
  194. */
  195. - (void)enumerateObjectsWithBlock:(AWSTMDiskCacheObjectBlock)block completionBlock:(AWSTMDiskCacheBlock)completionBlock;
  196. #pragma mark -
  197. /// @name Synchronous Methods
  198. /**
  199. Retrieves the object for the specified key. This method blocks the calling thread until the
  200. object is available.
  201. @see objectForKey:block:
  202. @param key The key associated with the object.
  203. @result The object for the specified key.
  204. */
  205. - (id <NSCoding>)objectForKey:(NSString *)key;
  206. /**
  207. Retrieves the file URL for the specified key. This method blocks the calling thread until the
  208. url is available. Do not use this URL anywhere but on the <sharedQueue>. This method probably
  209. shouldn't even exist, just use the asynchronous one.
  210. @see fileURLForKey:block:
  211. @param key The key associated with the object.
  212. @result The file URL for the specified key.
  213. */
  214. - (NSURL *)fileURLForKey:(NSString *)key;
  215. /**
  216. Stores an object in the cache for the specified key. This method blocks the calling thread until
  217. the object has been stored.
  218. @see setObject:forKey:block:
  219. @param object An object to store in the cache.
  220. @param key A key to associate with the object. This string will be copied.
  221. */
  222. - (void)setObject:(id <NSCoding>)object forKey:(NSString *)key;
  223. /**
  224. Removes the object for the specified key. This method blocks the calling thread until the object
  225. has been removed.
  226. @param key The key associated with the object to be removed.
  227. */
  228. - (void)removeObjectForKey:(NSString *)key;
  229. /**
  230. Removes all objects from the cache that have not been used since the specified date.
  231. This method blocks the calling thread until the cache has been trimmed.
  232. @param date Objects that haven't been accessed since this date are removed from the cache.
  233. */
  234. - (void)trimToDate:(NSDate *)date;
  235. /**
  236. Removes objects from the cache, largest first, until the cache is equal to or smaller than the
  237. specified byteCount. This method blocks the calling thread until the cache has been trimmed.
  238. @param byteCount The cache will be trimmed equal to or smaller than this size.
  239. */
  240. - (void)trimToSize:(NSUInteger)byteCount;
  241. /**
  242. Removes objects from the cache, ordered by date (least recently used first), until the cache is equal to or
  243. smaller than the specified byteCount. This method blocks the calling thread until the cache has been trimmed.
  244. @param byteCount The cache will be trimmed equal to or smaller than this size.
  245. */
  246. - (void)trimToSizeByDate:(NSUInteger)byteCount;
  247. /**
  248. Removes all objects from the cache. This method blocks the calling thread until the cache has been cleared.
  249. */
  250. - (void)removeAllObjects;
  251. /**
  252. Loops through all objects in the cache (reads and writes are suspended during the enumeration). Data is not actually
  253. read from disk, the `object` parameter of the block will be `nil` but the `fileURL` will be available.
  254. This method blocks the calling thread until all objects have been enumerated.
  255. @param block A block to be executed for every object in the cache.
  256. @warning Do not call this method within the event blocks (<didRemoveObjectBlock>, etc.)
  257. Instead use the asynchronous version, <enumerateObjectsWithBlock:completionBlock:>.
  258. */
  259. - (void)enumerateObjectsWithBlock:(AWSTMDiskCacheObjectBlock)block;
  260. #pragma mark -
  261. /// @name Background Tasks
  262. /**
  263. Set a global manager to be used for setting up/tearing down any background tasks needed by TMCache.
  264. @param backgroundTaskManager Background task manager.
  265. */
  266. + (void)setBackgroundTaskManager:(id <AWSTMCacheBackgroundTaskManager>)backgroundTaskManager;
  267. @end