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
這樣的方式實現,不管有多少個屬性,幾行程式碼就搞定了!