Runtime使用场景 - 序列化和反序列化

2017-11-29  本文已影响16人  岁月丿静好

Runtime 有什么用?

1.利用Runtime运行时,在程序的运行过程中,动态创建一个类

2.利用Runtime运行时,在程序运行中动态修改一个类的属性/方法

3.利用Runtime运行时,遍历一个类的所有属性和方法

这里来介绍一下怎么利用在Runtime运行时,通过遍历一个类的所有属性来实现序列化和反序列化

注:这里讲的是复杂对象的归档,基本数据类型的归档这里暂不做介绍

相比常规写法的优点:

1.快捷,一般开发中模型的属性非常多,如果用常规的方法,需要逐个进行编码反编码,想想就痛苦

2.省心,不用去管每个属性的类型

3.省事,代码可复用,新建模型的时候,可直接复用这两端段编码反编码这两段代码,只用在一处修改模型名称即可

效果示例

代码示例:对Person的属性进行编码和反编码(先遵循NSCoding协议)

1.编码

//编码

- (void)encodeWithCoder:(NSCoder *)aCoder {

//常规写法

/*

[aCoder encodeObject:_name forKey:@"name"];

[aCoder encodeObject:_gender forKey:@"gender"];

[aCoder encodeInteger:_age forKey:@"age"];

*/

//Runtime写法

//1.导入头文件

//2.获取这个类的所有成员变量列表的指针列表(这个可以在程序的任何地方获取,获取的成员变量包括这个类的私有属性)

unsigned int count = 0;

//c语言里面,如果传递一个基本数据类型的指针,那一般都是需要在函数内部修改它的值!

Ivar * ivars = class_copyIvarList([Person class], &count);

for (int i = 0; i< count; i++) {

//拿出属性的名称

Ivar ivar = ivars[i];

const char * name = ivar_getName(ivar);

//C语言字符串转化为OC字符串

NSString * KEY = [NSString stringWithUTF8String:name];

//取出属性对应的值 KVC

id value = [self valueForKey:KEY];

//编码

[aCoder encodeObject:value forKey:KEY];

}

//注意:C语言里面需要释放指针

free(ivars);

}

2.反编码

//反编码

- (instancetype)initWithCoder:(NSCoder *)aDecoder {

self = [super init];

if (self) {

//常规写法

/*

_name  = [aDecoder decodeObjectForKey:@"name"];

_gender = [aDecoder decodeObjectForKey:@"gender"];

_age    = [aDecoder decodeIntegerForKey:@"age"];

*/

//runtime写法

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);

//C语言字符串转化为OC字符串

NSString * KEY = [NSString stringWithUTF8String:name];

//反编码

id value = [aDecoder decodeObjectForKey:KEY];

//将值设置到对应的属性上 KVC

[self setValue:value forKey:KEY];

}

//注意:C语言里面需要释放指针

free(ivars);

}

return self;

}

归档和反归档

1.归档

//归档路径

- (NSString *)getFilePath{

//注:这里存储的是二进制类型的数据,故文件后缀名随便写

return  [NSTemporaryDirectory() stringByAppendingPathComponent:_FileName];

}

//归档(序列化)

- (IBAction)archiveAction:(id)sender {

Person *per = [[Person alloc]init];

per.name  =  @"Jack";

per.age    =  20;

per.gender =  @"man";

//设置文件名 注:这里存储的是二进制类型的数据,故文件后缀名随便写

_FileName = [NSString stringWithFormat:@"%@%@",per.name,@".per"];

//归档

[NSKeyedArchiver archiveRootObject:per toFile:[self getFilePath]];

//检测是否归档成功

BOOL result = [[NSFileManager defaultManager] fileExistsAtPath:[self getFilePath]];

if (result) {

[SYProgressHUD showSuccessText:@"序列化成功"];

}else{

[SYProgressHUD showFailureText:@"序列化失败"];

}

}

2.反归档

//反归档(反序列化)

- (IBAction)unarchiveAction:(id)sender {

//解档

Person *per = [NSKeyedUnarchiver unarchiveObjectWithFile:[self getFilePath]];

//显示读取的文件

_showReadInfoLB.text = [NSString stringWithFormat:@"name: %@  gender: %@  age: %ld",per.name,per.gender,per.age];

NSLog(@"%@",_showReadInfoLB.text);

}

上一篇 下一篇

猜你喜欢

热点阅读