1
0
mirror of https://github.com/danog/Telegram.git synced 2024-12-04 02:17:51 +01:00
Telegram/Watch/Extension/TGFileCache.m
2016-02-25 01:03:51 +01:00

222 lines
7.0 KiB
Objective-C

#import "TGFileCache.h"
#import "TGStringUtils.h"
NSString *const TGFileCacheDomain = @"com.telegram.FileCache";
@interface TGFileCache ()
{
NSCache *_memoryCache;
dispatch_queue_t _queue;
NSURL *_url;
}
@end
@implementation TGFileCache
- (instancetype)init
{
return [self initWithName:nil useMemoryCache:true];
}
- (instancetype)initWithName:(NSString *)name useMemoryCache:(bool)useMemoryCache
{
return [self initWithName:name useMemoryCache:useMemoryCache useApplicationGroup:false];
}
- (instancetype)initWithName:(NSString *)name useMemoryCache:(bool)useMemoryCache useApplicationGroup:(bool)useApplicationGroup
{
self = [super init];
if (self != nil)
{
if (useMemoryCache)
_memoryCache = [[NSCache alloc] init];
_queue = dispatch_queue_create(TGFileCacheDomain.UTF8String, nil);
NSURL *baseURL = useApplicationGroup ? [TGFileCache baseAppGroupURL] : [TGFileCache baseURL];
if (name.length == 0)
_url = baseURL;
else
_url = [NSURL fileURLWithPath:name relativeToURL:baseURL];
dispatch_async(_queue, ^
{
if (![[NSFileManager defaultManager] fileExistsAtPath:_url.path])
{
NSError *error;
[[NSFileManager defaultManager] createDirectoryAtURL:_url withIntermediateDirectories:true attributes:nil error:&error];
}
});
}
return self;
}
- (void)fetchDataForKey:(NSString *)key synchronous:(bool)synchronous unserializeBlock:(id (^)(NSData *))unserializeBlock completion:(void (^)(id))completion
{
[self fetchDataForKey:key memoryOnly:false synchronous:synchronous unserializeBlock:unserializeBlock completion:completion];
}
- (void)fetchDataForKey:(NSString *)key memoryOnly:(bool)memoryOnly synchronous:(bool)synchronous unserializeBlock:(id (^)(NSData *))unserializeBlock completion:(void (^)(id))completion
{
if (completion == nil)
return;
void (^block)(void) = ^
{
id cachedObject = [_memoryCache objectForKey:key];
if (cachedObject != nil)
{
completion(cachedObject);
return;
}
if (!memoryOnly)
{
NSData *data = [[NSData alloc] initWithContentsOfURL:[self urlForKey:key] options:kNilOptions error:nil];
if (data.length > 0)
{
id result = data;
if (unserializeBlock != nil)
{
result = unserializeBlock(data);
[_memoryCache setObject:result forKey:key];
}
completion(result);
return;
}
}
completion(nil);
};
if (synchronous)
dispatch_sync(_queue, block);
else
dispatch_async(_queue, block);
}
- (void)cacheData:(NSData *)data key:(NSString *)key synchronous:(bool)synchronous completion:(void (^)(NSURL *))completion
{
[self cacheData:data key:key synchronous:synchronous serializeBlock:nil completion:completion];
}
- (void)cacheData:(NSObject<NSCoding> *)data key:(NSString *)key synchronous:(bool)synchronous serializeBlock:(NSData *(^)(NSObject<NSCoding> *))serializeBlock completion:(void (^)(NSURL *))completion
{
void (^block)(void) = ^
{
NSURL *url = [self urlForKey:key];
NSData *serializedData = nil;
if (serializeBlock != nil)
serializedData = serializeBlock(data);
else if ([data isKindOfClass:[NSData class]])
serializedData = (NSData *)data;
[serializedData writeToURL:url atomically:true];
if (completion != nil)
completion(url);
};
if (synchronous)
dispatch_sync(_queue, block);
else
dispatch_async(_queue, block);
}
- (void)cacheFileAtURL:(NSURL *)url key:(NSString *)key synchronous:(bool)synchronous completion:(void (^)(NSURL *))completion
{
[self cacheFileAtURL:url key:key synchronous:synchronous unserializeBlock:nil completion:completion];
}
- (void)cacheFileAtURL:(NSURL *)url key:(NSString *)key synchronous:(bool)synchronous unserializeBlock:(id (^)(NSData *))unserializeBlock completion:(void (^)(NSURL *))completion
{
void (^block)(void) = ^
{
NSURL *newUrl = [self urlForKey:key];
[[NSFileManager defaultManager] copyItemAtURL:url toURL:newUrl error:NULL];
if (completion != nil)
completion(newUrl);
if (unserializeBlock != nil && _memoryCache != nil)
{
NSData *data = [NSData dataWithContentsOfURL:url];
id result = unserializeBlock(data);
[_memoryCache setObject:result forKey:key];
}
};
if (synchronous)
dispatch_sync(_queue, block);
else
dispatch_async(_queue, block);
}
- (void)clearCacheSynchronous:(bool)synchronous
{
void (^block)(void) = ^
{
NSArray *contents = [[NSFileManager defaultManager] contentsOfDirectoryAtURL:_url includingPropertiesForKeys:nil options:kNilOptions error:NULL];
for (NSURL *url in contents)
[[NSFileManager defaultManager] removeItemAtURL:url error:NULL];
};
if (synchronous)
dispatch_sync(_queue, block);
else
dispatch_async(_queue, block);
}
- (bool)hasDataForKey:(NSString *)key
{
return [[NSFileManager defaultManager] fileExistsAtPath:[self urlForKey:key].path];
}
- (NSURL *)urlForKey:(NSString *)key
{
NSString *fileName = [TGStringUtils md5WithString:key];
if (self.defaultFileExtension != nil)
fileName = [fileName stringByAppendingPathExtension:self.defaultFileExtension];
return [NSURL fileURLWithPath:[_url.path stringByAppendingPathComponent:fileName]];
}
+ (NSURL *)baseURL
{
static dispatch_once_t onceToken;
static NSURL *baseURL;
dispatch_once(&onceToken, ^
{
NSString *cachesPath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, true)[0];
baseURL = [[NSURL alloc] initFileURLWithPath:[cachesPath stringByAppendingPathComponent:TGFileCacheDomain]];
});
return baseURL;
}
+ (NSURL *)baseAppGroupURL
{
static dispatch_once_t onceToken;
static NSURL *baseAppGroupURL;
dispatch_once(&onceToken, ^
{
NSURL *groupURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:[self groupName]];
baseAppGroupURL = [[NSURL alloc] initFileURLWithPath:[groupURL.path stringByAppendingPathComponent:TGFileCacheDomain]];
});
return baseAppGroupURL;
}
+ (NSString *)groupName
{
static NSString *groupName = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^
{
groupName = [@"group." stringByAppendingString:[[NSBundle mainBundle] bundleIdentifier]];
if ([groupName hasSuffix:@".watchkitapp.watchkitextension"])
groupName = [groupName substringWithRange:NSMakeRange(0, groupName.length - @".watchkitapp.watchkitextension".length)];
});
return groupName;
}
@end