runtime之实现对象序列化
/*
iOS序列化,将对象转成二进制,保存到本地
*/
定义一个对象,让它实现NSCoding协议,保证对象的编码和解码,person有三个属性
@interface Person : NSObject <NSCoding>
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) int age;
@property (nonatomic, copy) NSString *gender;
@end
#import "Person.h"
#import <objc/message.h>
@implementation Person
//编码
- (void)encodeWithCoder:(NSCoder *)aCoder
{
/*原始写法,需要将对应的属性一个个设置一遍,若有很多属性,就会很麻烦,不灵活, 而且还要设置key,取的时候不小心写错的话,就会有问题
[aCoder encodeObject:_name forKey:@"name"];
[aCoder encodeInt:_age forKey:@"age"];
[aCoder encodeObject:_gender forKey:@"gender"];
*/
/*利用runtime*/
unsigned int count = 0;
Ivar *ivars = class_copyIvarList([Person class], &count); //得到Person所有的属性列表,ivars指向第0个属性
for (int i = 0; i < count; i ++) {
Ivar ivar = ivars[i]; //得到第i个属性
const char *paramName = ivar_getName(ivar); //得到属性名,带下划线的
NSString *key = [NSString stringWithUTF8String:paramName];
//得到属性的值,通过KVC,KVC会先去找没有下划线的属性名,若没有找到,就去找带下划线的属性名,如age属性,KVC会先找age,若找不到,则去找_age
id value = [self valueForKey:key];
[aCoder encodeObject:value forKey:key]; //把对应的值设置进去
}
}
//解码
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if (self) {
/*原始写法,需要将对应的属性一个个设置一遍,若有很多属性,就会很麻烦,不灵活, 而且还要设置key,取的时候不小心写错的话,就会有问题
_name = [aDecoder decodeObjectForKey:@"name"];
_age = [aDecoder decodeIntForKey:@"age"];
_gender = [aDecoder decodeObjectForKey:@"gender"];
*/
/*利用runtime*/
unsigned int count = 0;
Ivar *ivars = class_copyIvarList([Person class], &count); //得到Person所有的属性列表,ivars指向第0个属性
for (int i = 0; i < count; i ++) {
Ivar ivar = ivars[i]; //得到第i个属性
const char *paramName = ivar_getName(ivar); //得到属性名,带下划线的
NSString *key = [NSString stringWithUTF8String:paramName];
//将key对应的属性进行解码
id value = [aDecoder decodeObjectForKey:key];
//设置属性的值,通过KVC,KVC会先去找没有下划线的属性名,若没有找到,就去找带下划线的属性名,如age属性,KVC会先找age,若找不到,则去找_age
[self setValue:value forKey:key];
}
}
return self;
}