| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312 |
- //
- // XHCacheManager.m
- // XHImageViewer
- //
- // Created by 曾 宪华 on 14-2-18.
- // Copyright (c) 2014年 曾宪华 开发团队(http://iyilunba.com ) 本人QQ:543413507 本人QQ群(142557668). All rights reserved.
- //
- #import "XHCacheManager.h"
- #import "XHFileAttribute.h"
- #import "UIImage+Utility.h"
- #import "NSString+XHMD5.h"
- @interface XHCacheManager () {
- NSCache *_memoryCache;
- NSString *_cacheDirectoryPath;
- }
- @property (nonatomic, strong) NSString *identifier;
- @end
- @implementation XHCacheManager
- + (instancetype)shareCacheManager {
- return self.manager;
- }
- + (XHCacheManager *)cacheManagerWithIdentifier:(NSString *)identifier {
- return [[XHCacheManager alloc] initWithIdentifier:identifier];
- }
- - (id)init {
- return self.class.manager;
- }
- + (XHCacheManager *)manager {
- static XHCacheManager *sharedInstance = nil;
- static dispatch_once_t onceToken;
-
- dispatch_once(&onceToken, ^{
- sharedInstance = [[XHCacheManager alloc] initWithIdentifier:NSStringFromClass(self)];
- });
- return sharedInstance;
- }
- - (id)initWithIdentifier:(NSString *)identifier {
- if(identifier.length <= 0) {
- return self.class.manager;
- }
-
- self = [super init];
- if(self) {
- _memoryCache = [NSCache new];
- _memoryCache.countLimit = 50;
- self.identifier = identifier;
- }
- return self;
- }
- - (void)dealloc {
- [_memoryCache removeAllObjects];
- }
- #pragma mark- Uitility
- + (void)_checkWorkspace:(NSString*)rootDir
- {
- BOOL isDirectory = NO;
- BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:rootDir isDirectory:&isDirectory];
-
- if(!exists || !isDirectory){
- [[NSFileManager defaultManager] createDirectoryAtPath:rootDir withIntermediateDirectories:YES attributes:nil error:nil];
- }
-
- for(int i=0; i<16; i++) {
- for(int j=0; j<16; j++) {
- NSString *subDir = [NSString stringWithFormat:@"%@/%X%X", rootDir, i, j];
- isDirectory = NO;
- exists = [[NSFileManager defaultManager] fileExistsAtPath:subDir isDirectory:&isDirectory];
- if(!exists || !isDirectory){
- [[NSFileManager defaultManager] createDirectoryAtPath:subDir withIntermediateDirectories:YES attributes:nil error:nil];
- }
- }
- }
- }
- #pragma mark- directory operation
- - (NSString *)_cacheDirectory {
- if(_cacheDirectoryPath == nil){
- NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
- _cacheDirectoryPath = [paths.lastObject stringByAppendingPathComponent:self.identifier.MD5Hash];
- [self.class _checkWorkspace:_cacheDirectoryPath];
- }
-
- return _cacheDirectoryPath;
- }
- - (NSArray *)_fileAttributesInWorkSpace {
- NSString *rootDir = self._cacheDirectory;
- NSMutableArray *files = [NSMutableArray array];
-
- for(int i=0; i<16; i++) {
- for(int j=0; j<16; j++) {
- NSString *subDir = [NSString stringWithFormat:@"%@/%X%X", rootDir, i, j];
- NSArray *list = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:subDir error:nil];
-
- for(id name in list) {
- NSString *filePath = [NSString stringWithFormat:@"%@/%@", subDir, name];
- NSDictionary *attr = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:nil];
- if(attr) {
- [files addObject:[[XHFileAttribute alloc] initWithPath:filePath attributes:attr]];
- }
- }
- }
- }
- return files;
- }
- - (NSString *)_pathForHash:(NSString *)hash {
- return [NSString stringWithFormat:@"%@/%@/%@", [self _cacheDirectory], [hash substringToIndex:2], hash];
- }
- #pragma mark- Caching control
- - (void)limitNumberOfCacheFiles:(NSInteger)numberOfCacheFiles {
- NSArray *list = [self _fileAttributesInWorkSpace];
-
- NSSortDescriptor *dsc = [NSSortDescriptor sortDescriptorWithKey:@"fileModificationDate" ascending:NO];
- list = [list sortedArrayUsingDescriptors:@[dsc]];
-
- for(NSInteger i = numberOfCacheFiles; i < list.count; ++i){
- XHFileAttribute *file = list[i];
- [[NSFileManager defaultManager] removeItemAtPath:file.filePath error:nil];
- }
- }
- - (void)_didAccessToDataForHash:(NSString *)hash {
- NSString *path = [self _pathForHash:hash];
-
- NSError *err = nil;
- NSFileManager *fileManager = [NSFileManager defaultManager];
- NSMutableDictionary *fileAttribute = [[fileManager attributesOfItemAtPath:path error:&err] mutableCopy];
-
- if(err) { return; }
-
- fileAttribute[NSFileModificationDate] = [NSDate date];
- [fileManager setAttributes:fileAttribute ofItemAtPath:path error:nil];
- }
- - (void)removeCacheForURL:(NSURL *)url {
- if(url.absoluteString.length>0){
- [self _removeCacheForHash:url.absoluteString.MD5Hash];
- }
- }
- - (void)_removeCacheForHash:(NSString *)hash {
- [_memoryCache removeObjectForKey:hash];
-
- [[NSFileManager defaultManager] removeItemAtPath:[self _pathForHash:hash] error:nil];
- }
- - (void)removeCacheDirectory {
- [_memoryCache removeAllObjects];
- [[NSFileManager defaultManager] removeItemAtPath:[self _cacheDirectory] error:nil];
-
- _cacheDirectoryPath = nil;
- }
- #pragma mark- NSData caching
- - (void)storeData:(NSData *)data forURL:(NSURL *)url storeMemoryCache:(BOOL)storeMemoryCache {
- if(data && url.absoluteString.length > 0){
- [self _storeData:data forHash:url.absoluteString.MD5Hash storeMemoryCache:storeMemoryCache];
- }
- }
- - (void)_storeData:(NSData *)data forHash:(NSString *)hash storeMemoryCache:(BOOL)storeMemoryCache {
- [self _didAccessToDataForHash:hash];
-
- if(storeMemoryCache) {
- [_memoryCache setObject:data forKey:hash];
- }
- [data writeToFile:[self _pathForHash:hash] atomically:NO];
- }
- - (NSData *)localCachedDataWithURL:(NSURL *)url {
- if(url.absoluteString.length > 0){
- return [self _localCachedDataWithHash:url.absoluteString.MD5Hash];
- }
- return nil;
- }
- - (NSData *)_localCachedDataWithHash:(NSString *)hash {
- [self _didAccessToDataForHash:hash];
- return [NSData dataWithContentsOfFile:[self _pathForHash:hash]];
- }
- - (NSData *)_cachedDataWithHash:(NSString *)hash storeMemoryCache:(BOOL)storeMemoryCache {
- NSData *data = [_memoryCache objectForKey:hash];
- if(data){
- [self _didAccessToDataForHash:hash];
- return data;
- }
-
- data = [self _localCachedDataWithHash:hash];
- if(storeMemoryCache && data!=nil){
- [_memoryCache setObject:data forKey:hash];
- }
- return data;
- }
- - (NSData *)dataWithURL:(NSURL *)url storeMemoryCache:(BOOL)storeMemoryCache {
- if(url.absoluteString.length == 0){
- return nil;
- }
- return [self _cachedDataWithHash:url.absoluteString.MD5Hash storeMemoryCache:storeMemoryCache];
- }
- - (BOOL)existsDataForURL:(NSURL *)url {
- if(url.absoluteString.length > 0){
- NSString *path = [self _pathForHash:url.absoluteString.MD5Hash];
-
- BOOL isDirectory = YES;
- BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDirectory];
-
- return (exists && !isDirectory);
- }
- return NO;
- }
- #pragma mark- UIImage caching
- - (void)storeMemoryCacheWithImage:(UIImage *)image forURL:(NSURL *)url {
- if(image && url.absoluteString.length > 0){
- [self storeMemoryCacheWithImage:image forHash:url.absoluteString.MD5Hash];
- }
- }
- - (void)storeMemoryCacheWithImage:(UIImage *)image forHash:(NSString *)hash {
- [_memoryCache setObject:image forKey:hash];
- }
- - (UIImage *)imageWithURL:(NSURL *)url storeMemoryCache:(BOOL)storeMemoryCache {
- if(url.absoluteString.length == 0){
- return nil;
- }
-
- id data = [self dataWithURL:url storeMemoryCache:NO];
-
- if(data) {
- UIImage *image = nil;
-
- if([data isKindOfClass:[NSData class]]) {
- image = [UIImage fastImageWithData:data];
- }
- else if([data isKindOfClass:[UIImage class]]){
- image = (UIImage*)data;
- }
-
- if(image){
- if(storeMemoryCache){
- [self storeMemoryCacheWithImage:image forURL:url];
- }
- return image;
- }
- }
- return nil;
- }
- #pragma mark- wrapper
- + (void)limitNumberOfCacheFiles:(NSInteger)numberOfCacheFiles {
- [self.manager limitNumberOfCacheFiles:numberOfCacheFiles];
- }
- + (void)removeCacheForURL:(NSURL *)url {
- [self.manager removeCacheForURL:url];
- }
- + (void)removeCacheDirectory {
- [self.manager removeCacheDirectory];
- }
- + (void)storeData:(NSData *)data forURL:(NSURL *)url storeMemoryCache:(BOOL)storeMemoryCache {
- [self.manager storeData:data forURL:url storeMemoryCache:storeMemoryCache];
- }
- + (NSData *)localCachedDataWithURL:(NSURL *)url {
- return [self.manager localCachedDataWithURL:url];
- }
- + (NSData *)dataWithURL:(NSURL *)url storeMemoryCache:(BOOL)storeMemoryCache {
- return [self.manager dataWithURL:url storeMemoryCache:storeMemoryCache];
- }
- + (void)storeMemoryCacheWithImage:(UIImage*)image forURL:(NSURL*)url {
- [self.manager storeMemoryCacheWithImage:image forURL:url];
- }
- + (UIImage *)imageWithURL:(NSURL *)url storeMemoryCache:(BOOL)storeMemoryCache {
- return [self.manager imageWithURL:url storeMemoryCache:storeMemoryCache];
- }
- + (BOOL)existsDataForURL:(NSURL *)url {
- return [self.manager existsDataForURL:url];
- }
- @end
|