iOS之序列化与反序列化
所谓的序列化和反序列化就是将数据结构或对象和二进制串之间相互转换的过程;
本人的理解是当你于写数据需要本地存储时,即将你的数据写到硬盘上的时候,你就必须对他进行序列化,转换成二进制文件,从而便于在磁盘上的读写,同理在取出的时候必须将其在反序列化,这样才能将数据读出来,就好比加密和揭秘的过程。
在ios应用中如果需要保存大对象数据可以采用xml文件或者属性文件方式,但由于采用的纯文本方式保密性不够,如将保存数据封装为自定义类的实例通过序列化的二进制方式进行保存,这样安全性会有所提高。
具有序列化能力的类必须实现NSCoding协议的两个函数:
-(void) encodeWithCoder:(NSCoder *)encoder;
-(id) initWithCoder:(NSCoder *)decoder;
需求:使用NSUserDefaults存储对象,比如登录的时候直接把用户的信息转对象存储到本地。等要用的时候在拿出来用。但是NSUserDefaults并不能存储对象,所以要把对象进行序列化和反序列化。转为二进制进行存储。
以下附上代码实例:
对象模型.h文件声明的属性:
@property (nonatomic , copy) NSString *name;
对象模型.m文件实现的序列化与反序列化方法
//实现序列化和反序列化 - (void)encodeWithCoder:(NSCoder*)aCoder{ [aCoder encodeObject:self.name forKey:@"name"]; } - (id)initWithCoder:(NSCoder*)decoder{ if (self= [super init]) { if (decoder == nil) { return self; } self.name= [decoder decodeObjectForKey:@"name"]; } return self; }
以下是生成对象、序列化存储、反序列化读取的过程:
// 自定义对象存储 WFModel *model = [[WFModel alloc] init]; model.name = @"咿呀呀"; //存储 NSData *data = [NSKeyedArchiver archivedDataWithRootObject:model]; [[NSUserDefaults standardUserDefaults] setObject:data forKey:@"model"]; //读取 NSData *deData = [[NSUserDefaults standardUserDefaults]objectForKey:@"model"]; WFModel *deStu = [NSKeyedUnarchiver unarchiveObjectWithData:deData]; NSLog(@"deStu---%@",deStu.name);
------success------
2019-2-22 补充一种新的序列化方式,之前是常规的方式,现在的是利用runtime实现的
首先声明头文件
#import<objc/runtime.h>
- (void)encodeWithCoder:(NSCoder *)coder { NSLog(@"实现codeing协议"); //告诉系统归档的属性是哪些 unsigned int count = 0;//表示对象的属性个数 Ivar *ivars = class_copyIvarList([BaseModel class], &count); for (int i = 0; i<count; i++) { //拿到Ivar Ivar ivar = ivars[i]; const char *name = ivar_getName(ivar);//获取到属性的C字符串名称 NSString *key = [NSString stringWithUTF8String:name];//转成对应的OC名称 //归档 -- 利用KVC [coder encodeObject:[self valueForKey:key] forKey:key]; } free(ivars);//在OC中使用了Copy、Creat、New类型的函数,需要释放指针!!(注:ARC管不了C函数) } - (instancetype)initWithCoder:(NSCoder *)coder { self = [super init]; if (self) { //解档 unsigned int count = 0; Ivar *ivars = class_copyIvarList([BaseModel class], &count); for (int i = 0; i<count; i++) { //拿到Ivar Ivar ivar = ivars[i]; const char *name = ivar_getName(ivar); NSString *key = [NSString stringWithUTF8String:name]; //解档 id value = [coder decodeObjectForKey:key]; // 利用KVC赋值 [self setValue:value forKey:key]; } free(ivars); } return self; }
//注:使用runtime的好处不言而喻,无论对象有多少属性都可以通过这个for循环搞定,非常棒。
然后就可以的愉快的玩耍啦