前言:个人觉得开发人员最大的悲哀莫过于懂得使用却不明白其中的原理.在代码之前我觉得还是有必要简单阐述下相关的一些知识点. 因为文章或深或浅总有适合的人群.若有朋友发现了其中不正确的观点还望多多指出,不胜感激.
承接上篇博客我们来看看IOS开发中是如何将一个自定义的对象进行归档的
本篇博客将介绍以下几个方面的内容
本篇博客将介绍以下几个方面的内容
1)普通的单个对象归档操作
2)拥有继承关系的对象归档
3)同时将多个对象进行归档
2)拥有继承关系的对象归档
3)同时将多个对象进行归档
1.普通的单个对象归档操作
首先我们来看下最简单的单个对象归档操作
1.自定义一个跟小明一样有名的类(Person)
1.自定义一个跟小明一样有名的类(Person)
直接上代码 :
Person.h
1 #import <Foundation/Foundation.h> 2 3 @interface Person : NSObject<NSCoding> 4 5 /** 6 * 姓名 7 */ 8 @property (nonatomic, strong) NSString *name ; 9 10 /** 11 * 地址 12 */ 13 @property (nonatomic, strong) NSString *address ; 14 15 /** 16 * 年龄 17 */ 18 @property (nonatomic, assign) int age; 19 20 21 -(instancetype)initWithName:(NSString *)name address:(NSString *)address age:(int)age;//初始化方法 22 23 @end
Person.m
1 #import "Person.h" 2 3 @implementation Person 4 5 -(instancetype)initWithName:(NSString *)name address:(NSString *)address age:(int)age{ 6 if (self = [super init]) { 7 self.name = name; 8 self.address = address; 9 self.age = age; 10 } 11 return self; 12 } 13 14 //告知编译器,我们需要归档当前对象的哪些属性 15 -(void)encodeWithCoder:(NSCoder *)aCoder{ 16 17 [aCoder encodeObject:self.name forKey:@"name"]; 18 [aCoder encodeObject:self.address forKey:@"address"]; 19 [aCoder encodeInt: self.age forKey:@"age"]; 20 } 21 22 //告知编译器,解档时对应的属性 23 -(instancetype)initWithCoder:(NSCoder *)aDecoder{ 24 25 self.name = [aDecoder decodeObjectForKey:@"name"]; 26 self.address = [aDecoder decodeObjectForKey:@"address"]; 27 self.age = [aDecoder decodeIntForKey:@"age"]; 28 return self; 29 } 30 31 //重写description,方便调试查看对象属性信息 32 -(NSString *)description{ 33 return [NSString stringWithFormat:@"name : %@, address : %@,age : %d",self.name,self.address,self.age]; 34 } 35 36 @end
控制器代码1:归档
1 -(void)personArchive{ 2 //创建及初始化对象 3 Person *p = [[Person alloc] initWithName: @"jack" address:@"Mars" age:20]; 4 5 //定义归档路径 6 NSString *fullPath = [self fullPathWithFileName:@"person.data"]; 7 8 //进行归档 9 [NSKeyedArchiver archiveRootObject:p toFile:fullPath]; 10 11 NSLog(@"对象归档成功"); 12 }
控制器代码2:解档
1 -(void)personUnarchive{ 2 //指定路径 3 NSString *fullPath = [self fullPathWithFileName:@"person.data"]; 4 //解档操作 5 Person *p = [NSKeyedUnarchiver unarchiveObjectWithFile:fullPath]; 6 //打印结果 7 NSLog(@"%@",p); 8 9 }
注: fullPathWithFileName: 方法为便捷获取路径方法,代码如下
1 -(NSString *)fullPathWithFileName:(NSString *)fileName{ 2 3 NSString *documentDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject]; 4 //拼接完整路径并返回 5 return [documentDir stringByAppendingPathComponent:fileName]; 6 7 }
依次调用我们的归档和解档方法
[self personArchive];//归档 [self personUnarchive];//解档
结果如下:
至此我们已经实现了简单的单个对象的归档和解档操作,下面我们来看下继承关系下的对象的归档解档操作
2.拥有继承关系的对象归档和解档
定义一个Student类继承自Person类,代码如下
Student.h
1 #import "Person.h" 2 3 @interface Student : Person 4 5 /** 6 * 学校名称 7 */ 8 @property (nonatomic, strong) NSString *schoolName; 9 //快速初始化方法 10 -(instancetype)initWithName:(NSString *)name address:(NSString *)address age:(int)age schoolName:(NSString *)schoolName; 11 12 @end
Student.m
1 #import "Student.h" 2 3 @implementation Student 4 5 -(instancetype)initWithName:(NSString *)name address:(NSString *)address age:(int)age schoolName:(NSString *)schoolName{ 6 if (self = [super initWithName:name address:address age:age]) { 7 self.schoolName =schoolName; 8 } 9 return self; 10 } 11 12 13 -(void)encodeWithCoder:(NSCoder *)aCoder{ 14 15 [super encodeWithCoder:aCoder]; 16 17 [aCoder encodeObject:self.schoolName forKey:@"schoolName"]; 18 } 19 20 -(instancetype)initWithCoder:(NSCoder *)aDecoder 21 { 22 self = [super initWithCoder:aDecoder]; 23 self.schoolName = [aDecoder decodeObjectForKey:@"schoolName"]; 24 return self; 25 } 26 27 //重写description,方便调试查看属性信息 28 -(NSString *)description{ 29 30 //先拿到父类拥有的属性描述 31 NSString *str = [super description]; 32 //添加子类特有的描述,返回 33 return [str stringByAppendingString:[NSString stringWithFormat:@",schoolName : %@",self.schoolName]]; 34 } 35 @end
控制器方法1:归档
1 -(void)studentArchive{ 2 //声明一个子类对象 3 Student *stu = [[Student alloc] initWithName:@"小明" address:@"走廊" age:10 schoolName:@"剑桥大学"]; 4 //定义路径 5 NSString *fullpath = [self fullPathWithFileName:@"stu.data"]; 6 //归档操作 7 [NSKeyedArchiver archiveRootObject:stu toFile:fullpath]; 8 9 NSLog(@"归档成功"); 10 }
控制器方法2:解档
1 -(void)studentUnarchive{ 2 3 NSString *fullpath = [self fullPathWithFileName:@"stu.data"];//指定路径 4 Student *stu = [NSKeyedUnarchiver unarchiveObjectWithFile:fullpath];//解档 5 NSLog(@"%@",stu);//打印信息 6 }
依次调用上述两个方法,运行结果如下
3.同时将多个对象归档
演示代码如下:
1.归档
1 -(void)multipleArchive{ 2 //创建并初始化两个对象 3 Student *s0 = [[Student alloc]initWithName:@"name0" address:@"address0" age:10 schoolName:@"schoolName0"]; 4 Student *s1 = [[Student alloc]initWithName:@"name1" address:@"address1" age:20 schoolName:@"schoolName1"]; 5 6 //创建一个NSMutableData对象 7 NSMutableData *data = [NSMutableData data]; 8 NSKeyedArchiver *archive = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];//关联 9 10 [archive encodeObject:s0 forKey:@"student0"]; 11 [archive encodeObject:s1 forKey:@"student1"]; 12 13 [archive finishEncoding]; 14 //指定路径 15 NSString *fullpath = [self fullPathWithFileName:@"multiple.data"]; 16 //到这一步数据已缓存到data中,将其写入文件 17 [data writeToFile:fullpath atomically:YES]; 18 19 NSLog(@"多对象归档成功"); 20 21 }
02.解档:
1 -(void)multipleUnArchive{ 2 3 NSString *fullpath = [self fullPathWithFileName:@"multiple.data"];//指定路径 4 NSData *data = [NSData dataWithContentsOfFile:fullpath];//将数据解析成NSData对象 5 NSKeyedUnarchiver *unArchive = [[NSKeyedUnarchiver alloc]initForReadingWithData:data];//关联 6 Student *stu0 = [unArchive decodeObjectForKey:@"student0"]; 7 Student *stu1 = [unArchive decodeObjectForKey:@"student1"]; 8 [unArchive finishDecoding]; 9 NSLog(@"%@",stu0); 10 NSLog(@"%@",stu1); 11 12 }
运行结果如下图:
4.分析与简单总结
1.将一个对象归档的前提:
遵守NSCoding协议
实现两个方法:
encodeWithCoder://指定需要归档的属性
initWithCoder://指定需要解档的属性
2.继承关系的对象归档注意:实现两个方法:
encodeWithCoder://指定需要归档的属性
initWithCoder://指定需要解档的属性
在实现上述两个方法的时候记得调用其父类的方法
eg:
[super encodeWithCoder:aCoder];
self = [super initWithCoder:aDecoder];
3.多对象归档依赖于:NSData对象eg:
[super encodeWithCoder:aCoder];
self = [super initWithCoder:aDecoder];