Runtime之NSCoding的自動歸檔、接檔,runtimenscoding
為什麼要有Runtime的NSCoding的自動歸檔、接檔
大家所熟知的方法
//歸檔方法
- (void)encodeWithCoder:(NSCoder *)aCoder
{
//當學生被歸檔,學生要將成員都歸檔
[aCoder encodeObject:self.name forKey:@"name"];
[aCoder encodeInteger:self.age forKey:@"age"];
}
//解歸檔方法
- (id)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super init]) {
//當學生被解歸檔,學生要將成員都解歸檔
self.name = [aDecoder decodeObjectForKey:@"name"];
self.age = [aDecoder decodeIntegerForKey:@"age"];
}
return self;
}
這是因為資料少的情況下,如果資料有幾十條呢?寫幾十行這種代碼,你感覺怎麼樣?只要錯一個位元組,你這個資料就是沒有的。
這就出現了Runtime的自動歸檔、接檔。
Runtime有一個方法可以擷取當前類裡面的屬性列表,既然成員變數都能拿到,每一個成員變數所對應的key以及value當然也可以拿到,這樣就不需要自己一行一行的去歸檔,接檔了。
#import "person.h"
@implementation person
// 接檔讀資料
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if (self = [super init]) {
/*
OBJC_EXPORT Ivar *class_copyIvarList(Class cls, unsigned int *outCount)
Class cls 表示擷取那一個類的屬性列表
unsigned int *outCount 用於儲存擷取到屬性個數
*/
unsigned int count = 0;
Ivar *ivar = class_copyIvarList([self class], &count);
for (int i = 0; i < count; i++) {
//根據每一個屬性取出對應的key 注意key值是c語言的key
Ivar iva = ivar[i];
const charchar *key = ivar_getName(iva);
// 轉換為oc
NSString *strName = [NSString stringWithUTF8String:key];
//進行解檔取值
id value = [aDecoder decodeObjectForKey:strName];
//利用KVC對屬性賦值
[self setValue:value forKey:strName];
}
free(ivar);
}
return self;
}
// 歸檔存資料
- (void)encodeWithCoder:(NSCoder *)aCoder {
unsigned int count;
Ivar *ivar = class_copyIvarList([self class], &count);
for (int i=0; i < count; i++) {
Ivar iv = ivar[i];
const charchar *name = ivar_getName(iv);
NSString *strName = [NSString stringWithUTF8String:name];
//利用KVC取值
id value = [self valueForKey:strName];
[aCoder encodeObject:value forKey:strName];
}
free(ivar);
}
需要注意的一個細節就是當涉及到Runtime的時候。一定要記得記憶體的釋放。Xcode的ARC只適用於OC,對於C的指標,要記得手動free。
另外補充一下class_copyPropertyList和class_copyIvarList的區別:
class_copyPropertyList返回的僅僅是對象類的屬性(@property申明的屬性),而class_copyIvarList返回類的所有屬性和變數(包括在@interface大括弧中聲明的變數),下面做個簡單的測試。首先,定義一個WFrequencyManager類,然後在測試類別中寫一個測試函數testProperties調用上述兩個函數得到其返回結果再分別依次遍曆輸出其傳回值
執行上述測試函數後在控制台輸出結果為:
從上述執行結果可以很好的說明前者只擷取由@property聲明的屬性,而後者不但擷取了@property屬性,而且還擷取了@interface大括弧中聲明的變數