查看: 1997|回复: 0

[IOS开发教程] Runtime之NSCoding的自动归档、接档

发表于 2018-1-12 08:00:00

为什么要有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大括号中声明的变量



回复

使用道具 举报