為什麼要有Runtime的NSCoding的自動歸檔、接檔 大家所熟知的方法 //歸檔方法 - (void)encodeWithCoder:(NSCoder *)aCoder { //當學生被歸檔,學生要將成員都歸檔 [aCoder encodeObject:self.name forKey:@"n ...
為什麼要有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大括弧中聲明的變數