//
// JKCoding.h
// runtimeTest
//
// Created by wangdan on 15/6/24.
// Copyright (c) 2015年 wangdan. All rights reserved.
//
#ifndef runtimeTest_JKCoding_h
#define runtimeTest_JKCoding_h
#import <objc/runtime.h>
#import "NSObject+JKCoding.h"
/**
* 在.m文件中使用下面的宏,可以代替手写归档协议方法,支持
* 继承类,对象嵌套以及字典、数组中持有对象
*
* 使用步骤:
* 1 在所有需要归档的对象的.m文件中,引入该头文件
*
* 2.在相应的.m文件中,加入宏定义 #define JKClass XXX
* XXX 为当前类的类名
*
* 3.在需要归档的类的实现中,添加 JKCodingImplemention
*/
#define JKCodingImplemention \
- (void)encodeWithCoder:(NSCoder *)aCoder\
{\
if ([JKClass superclass] != [NSObject class]) {\
[super encodeWithCoder:aCoder];\
}\
unsigned int count = 0;\
objc_property_t *pList = class_copyPropertyList([JKClass class], &count);\
for (int i=0; i <count; i++) {\
NSString *key= [NSString stringWithFormat:@"%s", property_getName(pList[i])];\
[aCoder encodeObject:[self valueForKey:key] forKey:key];\
}\
free(pList);\
}\
\
- (id)initWithCoder:(NSCoder *)aDecoder\
{\
if ([JKClass superclass] != [NSObject class]) {\
self = [super initWithCoder:aDecoder];\
}\
else {\
self = [super init];\
}\
unsigned int count = 0;\
objc_property_t *pList = class_copyPropertyList([JKClass class], &count);\
for (int i=0; i <count; i++) {\
NSString *key= [NSString stringWithFormat:@"%s", property_getName(pList[i])];\
[self setValue:[aDecoder decodeObjectForKey:key] forKey:key]; \
}\
free(pList);\
return self;\
}
#endif
//
// JXTCacher.h
// jiaoxuetong
//
// Created by wangdan on 15/6/16.
// Copyright (c) 2015年 wangdan. All rights reserved.
//
#import <Foundation/Foundation.h>
typedef NS_ENUM(int, ArchiveType)
{
JXTFromJSONData,
JXTFromArchiveData
};
typedef NS_ENUM(int, CacheError)
{
CacheErrorNoError = 0, //无错误
CacheErrorCacheDataNotExist = -1, //取缓存时,缓存文件或数据不存在
CacheErrorBadUnarchiveData = -2, //解档时,源数据错误
CacheErrorBadArchiveData = -3, //归档时,输入源数据错误
CacheErrorBadInJsonData = -4, //存档序列化时输入源数据错误
CacheerrorBadOutJsonData = -5, //取档饭序列化时数据错误
CacheErrorReadFileFailed = -6, //写文件错误
CacheErrorWriteFileFailed = -7 //读文件错误
};
@class JXTCacher;
typedef void (^JXTCacheObjSetBlock)(JXTCacher *cacher,CacheError error);
typedef void (^JXTCacheObjGetBlock)(JXTCacher *cacher,id obj,CacheError error);
@interface JXTCacher : NSObject
@property (nonatomic,assign) long maxSize;
@property (nonatomic,readonly) long totalSize;
/**
* 单例模式 全局共享一个模型
*/
+(JXTCacher*)cacher;
#pragma mark - 缓存存取方法 -
/**
* 从内存中读取数据,存在或不存在均直接返回
*
* @param key 缓存数据key
*
* @param uid 用户id
*/
-(id)objectInMemoryForKey:(NSString*)key userId:(NSString*)uid;//
/**
* 从缓存、disk中读取数据 非阻塞方法
*
* @param key 缓存数据key
*
* @param uid 当前用户id
*
* @param block 取到缓存后回调
*/
-(void)objectForKey:(NSString*)key userId:(NSString*)uid achive:(JXTCacheObjGetBlock)block;
/**
* 存储对象
*
* @param obj 需要存储的对象
*
* @param key 对象存储的key
*
* @param uid 用户id
*
* @param needArchive 是否归档 needArchive 为1时
*
* 该对象必须实现归档和解档方法
*/
-(void)setObject:(id)obj forKey:(NSString *)key userId:(NSString *)uid useArchive:(ArchiveType)needArchive;
/**
* 缓存对象方法 非阻塞方法
*
* @param obj 待缓存对象 当前仅支持NSDictionary 和 NSArray
*
* 且其内部无其他对象模型
*
* @param key 缓存关键字
*
* @param uid 当前用户id
*
* @param needArchive 是否通过archive方法缓存
*
* @Param block 缓存完毕回调
*/
-(void)setObject:(id)obj forKey:(NSString*)key userId:(NSString*)uid useArchive:(ArchiveType)needArchive setted:(JXTCacheObjSetBlock)block;
#pragma mark - 缓存清除方法 -
/**
* 清除某个缓存
*
* @param key 缓存key
*
* @param uid 当前用户id
*/
-(void)clearObject:(NSString*)key userId:(NSString *)uid;
/**
* 删除某个用户对应的缓存
*
* @param uid 用户id
*/
-(void)clearObject:(NSString*)uid;
/**
* 清除所有缓存
*/
-(void)clearAllObject;
@end
//
// JXTCacher.m
// jiaoxuetong
//
// Created by wangdan on 15/6/16.
// Copyright (c) 2015年 wangdan. All rights reserved.
//
#import "JXTCacher.h"
#import <CommonCrypto/CommonDigest.h>
#define JXT_SIZE_OF_KEY_KEY @"jxtobjsizekey"
#define JXT_UID_OF_KEY_KEY @"uidofkey"
#define JXT_ARCHIVE_TYPE_OF_KEY @"archiveTypeOfKey"
#define JXTCACHE_FOLDER_PATH NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask,YES).lastObject
@interface JXTCacher()
@property (nonatomic,strong) dispatch_queue_t ioQueue_busy;
@property (nonatomic,strong) dispatch_queue_t ioQueue_idle;
@property (nonatomic,strong) NSMutableDictionary *sizeOfKey;
@property (nonatomic,strong) NSMutableDictionary *objOfKey;//存储经常交互的数据, 通过key索引
@property (nonatomic,strong) NSMutableDictionary *statusOfKey;//存储正在被访问的key状态
@property (nonatomic,strong) NSMutableDictionary *archiveTypeOfKey;
@end
@implementation JXTCacher
@synthesize totalSize = _totalSize;
-(id)init {
if (self = [super init]) {
[self initQueue];
[self initMemorySize];
[self initDiskPath];
[self initMemorySize];
[self initTemperyObj];
}
return self;
}
+(JXTCacher *)cacher {
static JXTCacher *cacher;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
cacher = [[JXTCacher alloc] init];
});
return cacher;
}
#pragma mark - 参数初始化
-(void)initQueue {
self.ioQueue_busy = dispatch_queue_create("com.iflytek.eclass.cache.iobusy", NULL);
self.ioQueue_idle = dispatch_queue_create("com.iflytek.eclass.cache.ioIdle", NULL);
}
-(void)initDiskPath {
// if (![[NSFileManager defaultManager] fileExistsAtPath:JXTCACHE_PATH isDirectory:NULL]) {
// [[NSFileManager defaultManager] createDirectoryAtPath:JXTCACHE_PATH withIntermediateDirectories:YES attributes:nil error:nil];
// }
}
-(void)initMemorySize {
NSDictionary *dic = [[NSUserDefaults standardUserDefaults] objectForKey:JXT_SIZE_OF_KEY_KEY];
self.sizeOfKey = [[NSMutableDictionary alloc] initWithDictionary:dic];
if (self.sizeOfKey == nil || self.sizeOfKey.allKeys.count ==0) {
self.totalSize = 0;
self.sizeOfKey = [[NSMutableDictionary alloc] init];
}
else {
for (NSString *key in self.sizeOfKey) {
self.totalSize += [[self.sizeOfKey objectForKey:key] longValue];
}
}
NSDictionary *archiveDic = [[NSUserDefaults standardUserDefaults] objectForKey:JXT_ARCHIVE_TYPE_OF_KEY];
if (archiveDic == nil) {
self.archiveTypeOfKey = [[NSMutableDictionary alloc] init];
}
else {
self.archiveTypeOfKey = [[NSMutableDictionary alloc] initWithDictionary:archiveDic];
}
}
-(void)initTemperyObj {
self.statusOfKey = [[NSMutableDictionary alloc] init];
self.objOfKey = [[NSMutableDictionary alloc] init];
}
#pragma mark - 属性 getter setter
-(void)setTotalSize:(long)totalSize {
_totalSize = totalSize;
}
#pragma mark - 字符串处理
-(NSString *)memoryKeyOfKey:(NSString *)key userId:(NSString *)uid
{
if (!key || !uid) {
return nil;
}
return [NSString stringWithFormat:@"%@|%@",key,uid];
return nil;//临时memory中的obect,需要通过key+uid一起索引
}
-(NSString *)md5:(NSString *)key {
const char *str = [key UTF8String];
if (str == NULL) {
str = "";
}
unsigned char r[CC_MD5_DIGEST_LENGTH];
CC_MD5(str, (CC_LONG)strlen(str), r);
NSString *fileName =
[NSString stringWithFormat:
@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
r[0], r[1], r[2], r[3], r[4], r[5], r[6],
r[7], r[8], r[9], r[10], r[11], r[12], r[13], r[14], r[15]];
return fileName;
}
-(NSString*)folderPath:(NSString *)uid {
return [NSString stringWithFormat:@"%@/%@",JXTCACHE_FOLDER_PATH,uid];
}
-(NSString*)filePath:(NSString *)uid key:(NSString*)key {
return [NSString stringWithFormat:@"%@/%@/%@",JXTCACHE_FOLDER_PATH,uid,[self md5:key]];
}
#pragma mark - 数据存储
//该函数已经被废弃了啊,但是考虑到有一些接口还在使用
//暂时还放在这里吧
-(void)setObject:(id)obj forKey:(NSString *)key userId:(NSString *)uid {
if (!uid || !key || !obj) {
return;
}
__weak typeof(self) weakSelf = self;
dispatch_async(self.ioQueue_busy, ^{
NSData *data = nil;
BOOL needWriteFile = 0;
NSString *folderPath = [self folderPath:uid];
NSString *filePath = [self filePath:uid key:key];
if ([obj isKindOfClass:[NSDictionary class]] || [obj isKindOfClass:[NSArray class]]) {
NSData *data = [NSJSONSerialization dataWithJSONObject:obj options:kNilOptions error:nil];
if (data == nil) {
return ;
}
}
else {
return ;
}
NSString *keyOfUidAndKey = [self memoryKeyOfKey:key userId:uid];
if (weakSelf.sizeOfKey[keyOfUidAndKey] != nil) {
if ([weakSelf.sizeOfKey[keyOfUidAndKey] longValue] != data.length) {
needWriteFile = YES;
[weakSelf.objOfKey setObject:obj forKey:keyOfUidAndKey];
weakSelf.totalSize += data.length-[weakSelf.sizeOfKey[keyOfUidAndKey] longValue];
[weakSelf.sizeOfKey setValue:[NSNumber numberWithLong:data.length] forKey:keyOfUidAndKey];
{
[weakSelf localStoreSizeOfKey:weakSelf key:JXT_SIZE_OF_KEY_KEY];
}
}
else {
needWriteFile = NO;
}
}
else {
needWriteFile = YES;
weakSelf.totalSize += data.length;
[weakSelf.objOfKey setObject:obj forKey:keyOfUidAndKey];
[weakSelf.sizeOfKey setValue:[NSNumber numberWithLong:data.length] forKey:keyOfUidAndKey];
{
[weakSelf localStoreSizeOfKey:weakSelf key:JXT_SIZE_OF_KEY_KEY];
}
}
if (needWriteFile) {
NSFileManager *fm = [NSFileManager defaultManager];
if (![fm fileExistsAtPath:folderPath isDirectory:NULL]) {
[fm createDirectoryAtPath:folderPath withIntermediateDirectories:YES attributes:nil error:nil];
}
if (![fm fileExistsAtPath:filePath isDirectory:NULL]) {
[fm createFileAtPath:filePath contents:nil attributes:nil];
}
}
NSError *error = [[NSError alloc] init];
BOOL writeResult=[data writeToFile:filePath options:NSDataWritingAtomic error:&error];
if (writeResult == 0) {
NSLog(@"error is %@",error.domain);
}
});//end of dispatch_async
}
-(void)setObject:(id)obj forKey:(NSString *)key userId:(NSString *)uid useArchive:(ArchiveType)needArchive
{
if (!uid || !key || !obj) {
return;
}
__weak typeof(self) weakSelf = self;
dispatch_async(self.ioQueue_busy, ^{
id memoryObj = nil;
NSMutableData *data = nil;
if (!needArchive) {
if (![obj isKindOfClass:[NSDictionary class]] && [obj isKindOfClass:[NSArray class]]) {
return ;
}
NSData *middleData = [NSJSONSerialization dataWithJSONObject:obj options:kNilOptions error:nil];
if (!middleData) {
return ;
}
data = [[NSMutableData alloc] initWithData:middleData];
memoryObj = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
}
else {
NSData* middleData = [NSKeyedArchiver archivedDataWithRootObject:obj];
if (!middleData) {
return;
}
data = [[NSMutableData alloc] initWithData:middleData];
memoryObj = [NSKeyedUnarchiver unarchiveObjectWithData:data];
}
NSString *keyOfUidAndKey = [self memoryKeyOfKey:key userId:uid];
BOOL needWriteFile = 0;
NSString *folderPath = [self folderPath:uid];
NSString *filePath = [self filePath:uid key:key];
[self.archiveTypeOfKey setObject:[NSNumber numberWithInt:needArchive] forKey:keyOfUidAndKey];
[self localStoreArchiveTypeOfKey:self key:JXT_ARCHIVE_TYPE_OF_KEY];
if (weakSelf.sizeOfKey[keyOfUidAndKey] != nil) {
if ([weakSelf.sizeOfKey[keyOfUidAndKey] longValue] != data.length) {
needWriteFile = YES;
[weakSelf.objOfKey setObject:memoryObj forKey:keyOfUidAndKey];
weakSelf.totalSize += data.length-[weakSelf.sizeOfKey[keyOfUidAndKey] longValue];
[weakSelf.sizeOfKey setValue:[NSNumber numberWithLong:data.length] forKey:keyOfUidAndKey];
{
[weakSelf localStoreSizeOfKey:weakSelf key:JXT_SIZE_OF_KEY_KEY];
}
}
else {
needWriteFile = NO;
}
}
else {
needWriteFile = YES;
weakSelf.totalSize += data.length;
[weakSelf.objOfKey setObject:memoryObj forKey:keyOfUidAndKey];
[weakSelf.sizeOfKey setValue:[NSNumber numberWithLong:data.length] forKey:keyOfUidAndKey];
{
[weakSelf localStoreSizeOfKey:weakSelf key:JXT_SIZE_OF_KEY_KEY];
}
}
if (needWriteFile) {
NSFileManager *fm = [NSFileManager defaultManager];
if (![fm fileExistsAtPath:folderPath isDirectory:NULL]) {
[fm createDirectoryAtPath:folderPath withIntermediateDirectories:YES attributes:nil error:nil];
}
if (![fm fileExistsAtPath:filePath isDirectory:NULL]) {
[fm createFileAtPath:filePath contents:nil attributes:nil];
}
}
NSError *error = [[NSError alloc] init];
BOOL writeResult=[data writeToFile:filePath options:NSDataWritingAtomic error:&error];
if (writeResult == 0) {
}
});//end of dispatch_async
}
-(void)setObject:(id)obj forKey:(NSString*)key userId:(NSString*)uid useArchive:(ArchiveType)needArchive setted:(JXTCacheObjSetBlock)block
{
if (!uid || !key || !obj) {
return;
}
__weak typeof(self) weakSelf = self;
dispatch_async(self.ioQueue_busy, ^{
id memoryObj = nil;
NSMutableData *data = nil;
if (!needArchive) {
if (![obj isKindOfClass:[NSDictionary class]] && [obj isKindOfClass:[NSArray class]]) {
if (block) {
block(weakSelf,CacheErrorBadInJsonData);
}
return ;
};
NSData *middleData = [NSJSONSerialization dataWithJSONObject:obj options:kNilOptions error:nil];
if (!middleData) {
if (block) {
block(weakSelf,CacheErrorBadInJsonData) ;
}
return ;
}
data = [[NSMutableData alloc] initWithData:middleData];
memoryObj = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
}
else {
NSData* middleData = [NSKeyedArchiver archivedDataWithRootObject:obj];
if (!middleData) {
if (block) {
block(weakSelf,CacheErrorBadArchiveData) ;
}
return;
}
data = [[NSMutableData alloc] initWithData:middleData];
memoryObj = [NSKeyedUnarchiver unarchiveObjectWithData:data];
}
NSString *keyOfUidAndKey = [self memoryKeyOfKey:key userId:uid];
BOOL needWriteFile = 0;
NSString *folderPath = [self folderPath:uid];
NSString *filePath = [self filePath:uid key:key];
[self.archiveTypeOfKey setObject:[NSNumber numberWithInt:needArchive] forKey:keyOfUidAndKey];
[self localStoreArchiveTypeOfKey:self key:JXT_ARCHIVE_TYPE_OF_KEY];
if (weakSelf.sizeOfKey[keyOfUidAndKey] != nil) {
if ([weakSelf.sizeOfKey[keyOfUidAndKey] longValue] != data.length) {
needWriteFile = YES;
[weakSelf.objOfKey setObject:memoryObj forKey:keyOfUidAndKey];
weakSelf.totalSize += data.length-[weakSelf.sizeOfKey[keyOfUidAndKey] longValue];
[weakSelf.sizeOfKey setValue:[NSNumber numberWithLong:data.length] forKey:keyOfUidAndKey];
{
[weakSelf localStoreSizeOfKey:weakSelf key:JXT_SIZE_OF_KEY_KEY];
}
}
else {
needWriteFile = NO;
}
}
else {
needWriteFile = YES;
weakSelf.totalSize += data.length;
[weakSelf.objOfKey setObject:memoryObj forKey:keyOfUidAndKey];
[weakSelf.sizeOfKey setValue:[NSNumber numberWithLong:data.length] forKey:keyOfUidAndKey];
{
[weakSelf localStoreSizeOfKey:weakSelf key:JXT_SIZE_OF_KEY_KEY];
}
}
if (needWriteFile) {
NSFileManager *fm = [NSFileManager defaultManager];
if (![fm fileExistsAtPath:folderPath isDirectory:NULL]) {
[fm createDirectoryAtPath:folderPath withIntermediateDirectories:YES attributes:nil error:nil];
}
if (![fm fileExistsAtPath:filePath isDirectory:NULL]) {
[fm createFileAtPath:filePath contents:nil attributes:nil];
}
}
NSError *error = [[NSError alloc] init];
BOOL writeResult=[data writeToFile:filePath options:NSDataWritingAtomic error:&error];
if (writeResult == 0) {
if (block) {
block(weakSelf,CacheErrorWriteFileFailed);
}
}
if (block) {
block(weakSelf,CacheErrorNoError);
}
});//end of dispatch_async
}
-(id)objectInMemoryForKey:(NSString *)key userId:(NSString *)uid {
if (!uid || !key) {
return nil;
}
NSString *keyOfUidAndKey = [self memoryKeyOfKey:key userId:uid];
if (self.objOfKey[keyOfUidAndKey] != nil) {
return [self.objOfKey objectForKey:keyOfUidAndKey];
}
return nil;
}
-(void)objectForKey:(NSString *)key userId:(NSString *)uid achive:(JXTCacheObjGetBlock)block {
if (!uid || !key || !block) {
return;
}
__weak typeof(self) weakSelf = self;
dispatch_async(self.ioQueue_busy, ^{
NSString *keyOfUidAndKey = [weakSelf memoryKeyOfKey:key userId:uid];
if (weakSelf.objOfKey[keyOfUidAndKey] != nil) {
block(weakSelf,weakSelf.objOfKey[keyOfUidAndKey],CacheErrorNoError);
return;
}
NSString *filePath = [weakSelf filePath:uid key:key];
NSData *objData = [NSData dataWithContentsOfFile:filePath];
if (objData == nil) {
block(weakSelf,nil,CacheErrorCacheDataNotExist);
return;
}
id obj = nil;
BOOL archiveType = [[weakSelf.archiveTypeOfKey objectForKey:keyOfUidAndKey] intValue];
if (archiveType == JXTFromJSONData) {
@try {
obj = [NSJSONSerialization JSONObjectWithData:objData options:kNilOptions error:nil];
}
@catch (NSException *exception) {
[weakSelf clearObject:key userId:uid];
NSLog(@"got exception when unarchive %@",exception);
if (obj == nil) {
block(weakSelf,nil,CacheErrorBadUnarchiveData);
return ;
}
}
@finally {
}
}
else {
@try {
obj = [NSKeyedUnarchiver unarchiveObjectWithData:objData];
}
@catch (NSException *exception) {
[weakSelf clearObject:key userId:uid];
NSLog(@"got exception when unarchive %@",exception);
if (obj == nil) {
block(weakSelf,nil,CacheErrorBadUnarchiveData);
return ;
}
}
@finally {
}
}
if (weakSelf.objOfKey[keyOfUidAndKey] == nil) {
weakSelf.objOfKey[keyOfUidAndKey] = obj;
}
if (objData.length != [weakSelf.sizeOfKey[keyOfUidAndKey] longValue]) {
[weakSelf.objOfKey setObject:obj forKey:keyOfUidAndKey];
long oldLength = [weakSelf.sizeOfKey[keyOfUidAndKey] longValue];
weakSelf.totalSize = weakSelf.totalSize-oldLength+objData.length;
[weakSelf.sizeOfKey setValue:[NSNumber numberWithLong:objData.length] forKey:keyOfUidAndKey];
{
[weakSelf localStoreSizeOfKey:weakSelf key:JXT_SIZE_OF_KEY_KEY];
}
}
block(weakSelf,obj,CacheErrorNoError);
});
}
-(void)clearObject:(NSString *)key userId:(NSString *)uid {
if (!key || !uid) {
return;
}
NSString *keyOfUidAndKey = [self memoryKeyOfKey:key userId:uid];
__weak typeof(self) weakSelf = self;
dispatch_async(self.ioQueue_busy, ^{
NSString *filePath = [weakSelf filePath:uid key:key];
NSFileManager *fm = [NSFileManager defaultManager];
if ([fm removeItemAtPath:filePath error:nil]) {
long objSize = [weakSelf.sizeOfKey[keyOfUidAndKey] longValue];
weakSelf.totalSize -= objSize;
[weakSelf.sizeOfKey removeObjectForKey:keyOfUidAndKey];
[weakSelf.objOfKey removeObjectForKey:keyOfUidAndKey];
[weakSelf.archiveTypeOfKey removeObjectForKey:keyOfUidAndKey];
}
{
[weakSelf localStoreSizeOfKey:weakSelf key:JXT_SIZE_OF_KEY_KEY];
[weakSelf localStoreArchiveTypeOfKey:weakSelf key:JXT_ARCHIVE_TYPE_OF_KEY];
}
});
}
-(void)clearObject:(NSString*)uid {
if (!uid) {
return;
}
__weak typeof(self) weakSelf = self;
dispatch_async(self.ioQueue_busy, ^{
NSLog(@"删除某一个账号的id");
for (NSString *totalKey in weakSelf.sizeOfKey.allKeys) {
NSArray *keyArray = [totalKey componentsSeparatedByString:@"|"];
NSString *arrayUid = keyArray[1];
NSString *arrayKey = keyArray[0];
if (arrayUid == uid) {
NSFileManager *fm = [NSFileManager defaultManager];
NSString *filePath = [weakSelf filePath:arrayUid key:arrayKey];
if ([fm removeItemAtPath:filePath error:nil]) {
long objSize = [weakSelf.sizeOfKey[totalKey] longValue];
weakSelf.totalSize -= objSize;
[weakSelf.sizeOfKey removeObjectForKey:totalKey];
[weakSelf.objOfKey removeObjectForKey:totalKey];
[weakSelf.archiveTypeOfKey removeObjectForKey:totalKey];
}
}
}
[weakSelf localStoreArchiveTypeOfKey:weakSelf key:JXT_ARCHIVE_TYPE_OF_KEY];
[weakSelf localStoreSizeOfKey:weakSelf key:JXT_SIZE_OF_KEY_KEY];
});
}
-(void)clearAllObject {
__weak typeof(self) weakSelf = self;
dispatch_async(self.ioQueue_busy, ^{
NSFileManager *fm = [NSFileManager defaultManager];
for (NSString *key in weakSelf.sizeOfKey.allKeys) {
NSArray *uidKeyArray = [key componentsSeparatedByString:@"|"];
NSString *uid = uidKeyArray[1];
NSString *fileKey = uidKeyArray[0];
NSString *filePath = [weakSelf filePath:uid key:fileKey];
if ([fm removeItemAtPath:filePath error:nil]) {
long objSize = [weakSelf.sizeOfKey[key] longValue];
weakSelf.totalSize -= objSize;
[weakSelf.sizeOfKey removeObjectForKey:key];
[weakSelf.objOfKey removeObjectForKey:key];
[weakSelf.archiveTypeOfKey removeObjectForKey:key];
}
}
{
[weakSelf localStoreSizeOfKey:weakSelf key:JXT_SIZE_OF_KEY_KEY];
[weakSelf localStoreArchiveTypeOfKey:weakSelf key:JXT_ARCHIVE_TYPE_OF_KEY];
}
});
}
-(void)localStoreSizeOfKey:(id)owner key:(NSString*)key {
__weak JXTCacher* weakOwner = owner;
[[NSUserDefaults standardUserDefaults] setObject:weakOwner.sizeOfKey forKey:key];
}
-(void)localStoreArchiveTypeOfKey:(id)owner key:(NSString*)key {
__weak JXTCacher* weakOwner = owner;
[[NSUserDefaults standardUserDefaults] setObject:weakOwner.archiveTypeOfKey forKey:key];
}
#pragma mark -销毁对象
-(void)dealloc {
}
@end
//
// NSObject+JKCoding.h
// runtimeProject
//
// Created by wangdan on 15/6/20.
// Copyright (c) 2015年 wangdan. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
@interface NSObject (JKCoding)
/**
* 可以代替手写归档协议方法,支持
* 继承类,对象嵌套以及字典、数组中持有对象
*
*/
-(void)encodeWithCoder:(NSCoder *)aCoder;
-(id)initWithCoder:(NSCoder *)aDecoder;
/**
* 用于从字典生成模型类对象
*
*/
+(id)objectFromDic:(NSDictionary*)dic;
+(NSArray *)objectArrayFromArray:(NSArray *)array;
@end
//
// NSObject+JKCoding.m
// runtimeProject
//
// Created by wangdan on 15/6/20.
// Copyright (c) 2015年 wangdan. All rights reserved.
//
#import "NSObject+JKCoding.h"
@implementation NSObject (JKCoding)
-(void)encodeWithCoder:(NSCoder *)aCoder
{
Class currentClass = self.class;
if (currentClass == NSObject.class) {
return;
}
while (currentClass && currentClass != [NSObject class])
{
unsigned int count = 0;
objc_property_t *pList = class_copyPropertyList(currentClass, &count);
if (count>0) {
for (int i=0;i<count;i++) {
NSString *key = [NSString stringWithUTF8String:property_getName(pList[i])];
[aCoder encodeObject: [self valueForKey:key] forKey:key];
}
}
currentClass = class_getSuperclass(currentClass);
free(pList);
}
}
-(id)initWithCoder:(NSCoder *)aDecoder
{
Class currentClass = self.class;
if (currentClass == NSObject.class) {
return nil;
}
while (currentClass && currentClass != [NSObject class])
{
unsigned int count = 0;
objc_property_t *pList = class_copyPropertyList(currentClass, &count);
if (count > 0) {
for (int i = 0;i < count;i++) {
NSString *key = [NSString stringWithUTF8String:property_getName(pList[i])];
[self setValue:[aDecoder decodeObjectForKey:key] forKey:key];
}
}
currentClass = class_getSuperclass(currentClass);
free(pList);
}
return self;
}
+(id)objectFromDic:(NSDictionary*)dic
{
return [[self alloc] initFromDic:dic];
}
+(NSArray *)objectArrayFromArray:(NSArray *)array
{
if (array == nil || array.count == 0) {
return nil;
}
NSMutableArray *objArray = [[NSMutableArray alloc] init ];
[objArray enumerateObjectsUsingBlock:^(id objDic, NSUInteger idx, BOOL *stop) {
id obj = [[self alloc] initFromDic:objDic];
if (obj) {
[objArray addObject:obj];
}
}];
return objArray;
}
/*
-(id)initFromDic:(NSDictionary *)dic
{
if (self.class != [NSObject class]) {
self = [[self.class alloc] init];
}
else {
self = [self init];
}
if (self) {
Class currentClass = self.class;
NSMutableArray *propertyList = [[NSMutableArray alloc] init];
NSMutableArray *attributeNameList = [[NSMutableArray alloc] init];
while (currentClass && currentClass != NSObject.class) {
unsigned int count = 0;
objc_property_t *pList = class_copyPropertyList(currentClass, &count);
if (count>0) {
for (int i=0; i<count; i++) {
NSString *propertyString = [NSString stringWithUTF8String:property_getName(pList[i])];
[propertyList addObject:propertyString];
NSString *attributeString = [NSString stringWithUTF8String:property_getAttributes(pList[i])];
[attributeNameList addObject:attributeString];
}
}
free(pList);
currentClass = class_getSuperclass(currentClass);
}
if (propertyList.count == 0) {
return self;
}
for (int i=0; i<propertyList.count ; i++) {
NSString *key = propertyList[i];
NSString *propertyType = [self getClassNameFromPropertyName:attributeNameList[i]];
id obj = [dic objectForKey:key];
if (!obj) {
continue;
}
if (propertyType ==nil) {
[self setValue:obj forKey:key];
}
// else if ([propertyType isEqualToString:@"NSMutableArray"] || [propertyType isEqualToString:@"NSArray"]) {
else if (NSClassFromString(propertyType) == [NSArray class] || NSClassFromString(propertyType) == [NSMutableArray class]) {
if ([obj isKindOfClass:[NSArray class]]) {
NSMutableArray *objArray = [[NSMutableArray alloc] init];
SEL method = NSSelectorFromString(@"classNameForKeys");
if ([self respondsToSelector:method]) {
IMP imp = [self methodForSelector:method];
id (*func)(id, SEL) = (void *)imp;
Class keyClass = [func(self,method) objectForKey:key];
SEL objMethod = NSSelectorFromString(@"objectFromDic:");
IMP objImp = [keyClass methodForSelector:objMethod];
id (*objFunc)(id, SEL,id) = (void *)objImp;
if (keyClass && objImp) {
for (NSDictionary *dic in obj) {
id transferedObj = objFunc(keyClass,objMethod,dic);
if (transferedObj) {
[objArray addObject:transferedObj];
}
}
[self setValue:objArray forKey:key];
}
}
}
}
else {
Class keyClass = NSClassFromString(propertyType);
if (keyClass) {
SEL method = NSSelectorFromString(@"objectFromDic:");
IMP imp = [keyClass methodForSelector:method];
id (*func)(id, SEL,id) = (void *)imp;
if (imp) {
id transferedObj = func(keyClass,method,obj);
if (transferedObj) {
[self setValue:transferedObj forKey:key];
}
}
}
}
}
}
return self;
}
*/
-(id)initFromDic:(NSDictionary *)dic
{
if (self.class == NSObject.class) {
return nil;
}
else {
self = [self init];
}
if (self) {
Class currentClass = self.class;
NSMutableArray *propertyList = [[NSMutableArray alloc] init];
NSMutableArray *attributeNameList = [[NSMutableArray alloc] init];
while (currentClass && currentClass != NSObject.class)
{
unsigned int count = 0;
objc_property_t *pList = class_copyPropertyList(currentClass, &count);
if (count > 0)
{
for (int i = 0; i < count; i++)
{
NSString *propertyString = [NSString stringWithUTF8String:property_getName(pList[i])];
[propertyList addObject:propertyString];
NSString *attributeString = [NSString stringWithUTF8String:property_getAttributes(pList[i])];
[attributeNameList addObject:attributeString];
}
}
free(pList);
currentClass = class_getSuperclass(currentClass);
}
if (propertyList.count == 0) {
return self;
}
for (int i=0; i<propertyList.count ; i++) {
NSString *key = propertyList[i];
NSString *propertyType = [self getClassNameFromPropertyName:attributeNameList[i]];
id obj = [dic objectForKey:key];
if (obj == nil) {
continue;
}
if (propertyType == nil) {
[self setValue:obj forKey:key];
}
else if (([propertyType isEqualToString:@"NSMutableArray"] || [propertyType isEqualToString:@"NSArray"])
&& [obj isKindOfClass:[NSArray class]]) {
SEL classNameMethod = NSSelectorFromString(@"classNameForKeys");
if ([self respondsToSelector:classNameMethod]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
NSDictionary *classNameDic = (NSDictionary*)[self performSelector:classNameMethod];
Class propertyClass = [classNameDic objectForKey:key];
if (propertyClass) {
NSMutableArray *objArray = [[NSMutableArray alloc] init];
for (NSDictionary *objDic in obj) {
id transferedObj = [propertyClass objectFromDic:objDic];
if (transferedObj) {
[objArray addObject:transferedObj];
}
}
[self setValue:objArray forKey:key];
}
else {
[self setValue:obj forKey:key];
}
}
else {
[self setValue:obj forKey:key];
}
}
else {
Class keyClass = NSClassFromString(propertyType);
if (keyClass) {
id transferedObj = [keyClass objectFromDic:obj];
if (transferedObj) {
[self setValue:transferedObj forKey:key];
}
}
}
}
}
return self;
}
-(NSString *)getClassNameFromPropertyName:(NSString*)name
{
if (name == nil) {
return nil;
}
NSString * className = nil;
if ([[name substringWithRange:NSMakeRange(1, 1)] isEqualToString:@"@"]) {
NSString *subRangeString = [name substringWithRange:NSMakeRange(3, 3)];
if ([subRangeString isEqualToString:@"NSA"] || [subRangeString isEqualToString:@"NSM"]) {
className = @"NSArray";
}
else {
NSString *otherSystemString = [name substringWithRange: NSMakeRange(3, 2)];
if ([otherSystemString isEqualToString:@"NS"]) {
className = nil;
}
else {
className = [[name componentsSeparatedByString:@"\""] objectAtIndex:1];
}
}
}
return className;
}
-(NSArray *)nomalObjTypeArray
{
NSArray *array = @[@"NSDictonary",@"NSMutalbeDictionary",@"NSString",
@"NSNumber",@"NSAttributeString",@"NSValue",@"NSArray",@"NSMutableArray",
@"NSData"];
return array;
}
@end