runtime-自动归档和解档
我们通常会在自定义模型数据持久化的过程中,遇到一个模型有许多个属性,那么我们需要对每个属性都实现一遍encodeObject和decodeObjectForKey方法,如果这样的模型有很多个,还真的是一个十分麻烦的事情。
model的.h
@interface Person : NSObject<NSCoding>
@property(nonatomic, assign) NSInteger age;
@property(nonatomic, strong) NSString * name;
@property(nonatomic, strong) NSString * sex;
/**
* 缓存对象
*
* @return 是否成功
*/
- (BOOL)setInstance;
/**
* 从缓存中取出对象
*
* @return 对象实例
*/
+ (nullable instancetype)getInstance;
/**
*从缓存中移除对象
*/
+ (void)removeInstance;
@end
model的.m
@implementation Person
- (void)encodeWithCoder:(NSCoder *)coder
{
//告诉系统归档的属性是哪些
// [coder encodeObject:self.name forKey:@"name"];
// [coder encodeInteger:self.age forKey:@"age"];
unsigned int count = 0;
Ivar *ivars = class_copyIvarList([Person class], &count);
for (int i = 0; i<count; i++)
{
Ivar ivar = ivars[i];
const char *name = ivar_getName(ivar);
NSString *key = [NSString stringWithUTF8String:name];
[coder encodeObject:[self valueForKey:key] forKey:key];
}
free(ivars);
}
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super init];
if (self) {
//解档
// self.name = [coder decodeObjectForKey:@"name"];
// self.age = [coder decodeIntegerForKey:@"age"];
unsigned int count = 0;
Ivar *ivars = class_copyIvarList([Person class], &count);
for (int i = 0; i<count; i++) {
Ivar ivar = ivars[i];
const char *name = ivar_getName(ivar);
NSString *key = [NSString stringWithUTF8String:name];
id value = [coder decodeObjectForKey:key];
[self setValue:value forKey:key];
}
free(ivars);
}
return self;
}
#pragma mark - 缓存对象
- (BOOL)setInstance
{
NSString *name = [NSString stringWithFormat:@"%@.gmldat", NSStringFromClass(self.class)];
NSString *path = [[self.class cachesFolder] stringByAppendingPathComponent:name];
return [self.class archiveObjectToCache:self toFile:path];
}
+ (instancetype)getInstance
{
NSString *name = [NSString stringWithFormat:@"%@.gmldat", NSStringFromClass(self.class)];
NSString *path = [[self.class cachesFolder] stringByAppendingPathComponent:name];
return [self unarchiveObjectFromCache:path];
}
+ (void)removeInstance
{
NSString *name = [NSString stringWithFormat:@"%@.gmldat", NSStringFromClass(self.class)];
NSString *path = [[self.class cachesFolder] stringByAppendingPathComponent:name];
[self removeObjectFromCache:path];
}
#pragma mark - Utils
//归档
+ (BOOL)archiveObjectToCache:(id)obj toFile:(NSString *)path
{
return [NSKeyedArchiver archiveRootObject:obj toFile:path];
}
//删除
+ (BOOL)removeObjectFromCache:(NSString *)path
{
return [self archiveObjectToCache:nil toFile:path];
}
//解档
+ (id)unarchiveObjectFromCache:(NSString *)path
{
return [NSKeyedUnarchiver unarchiveObjectWithFile:path];
}
+ (NSString *)cachesFolder
{
return NSTemporaryDirectory();
// return [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
}
@end
这样的方式实现,不管有多少个属性,几行代码就搞定了!