使用簡單的數據存儲有時候須要用到 NSCoding協議 實現其 encodeWithCoder 與 initWithCoder 方法代理
通常實現的姿式是這樣的:code
可是這樣會有一個缺陷, 若是咱們想加一個屬性, 就要再在NSCoding代理方法里加入屬性的序列化和反序列化操做, 不然會很容易致使項目崩潰, 那麼有沒有一種方式實現NSCOding協議而又不用再修改呢, 這時就須要用到強大的runtime了:blog
這樣寫的好處是無論有多少屬性, 這兩個方法都能經過runtime獲取全部屬性存取解決, 之後再添加任何屬性都不用擔憂NSCoding協議方法會有問題啦get
// copy代碼請下拉:string
// 歸檔it
- (void)encodeWithCoder:(NSCoder *)aCoder {class
unsigned int count = 0;List
//1.取出全部的屬性遍歷
objc_property_t *propertes = class_copyPropertyList([self class], &count);序列化
//2.遍歷的屬性
for (int i=0; i<count; i++) {
//獲取當前遍歷的屬性的名稱
const char *propertyName = property_getName(propertes[i]);
NSString *name = [NSString stringWithUTF8String:propertyName];
//利用KVC取出對應屬性的值
id value = [self valueForKey:name];
//歸檔到文件中
[aCoder encodeObject:value forKey:name];
}
}
// 解檔
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if (self = [super init]) {
unsigned int count =0;
//1.取出全部的屬性
objc_property_t *propertes = class_copyPropertyList([self class], &count);
//2.遍歷全部的屬性
for (int i = 0; i < count; i++) {
//獲取當前遍歷到的屬性名稱
const char *propertyName = property_getName(propertes[i]);
NSString *name = [NSString stringWithUTF8String:propertyName];
//解歸檔前遍歷獲得的屬性的值
id value = [aDecoder decodeObjectForKey:name];
[self setValue:value forKey:name];
}
}
return self;
}