由于复杂对象无法通过writeToFile:方法进行数据持久化,只能通过将复杂对象转换为NSData,通过writeToFile;进行数据持久化。
将复杂对象转换为NSData,通过归档;将NSData转换为复杂对象,通过反归档。
这里使用归档和反归档的时候需要在.h文件中导入一个协议<NSCoding>协议,注意这个协议比较特殊不需要指定代理对象。
第一步、导入代理实现他的俩个代理方法
Person.h
@interface Person : NSObject <NSCoding>
@property (nonatomic,retain)NSString *gender; // 性别
@property (nonatomic,retain)NSString *name; // 姓名
@property (nonatomic,assign)int age; // 年龄
@end
然后在Person.m文件中实现他的两个代理方法
// 归档 实际上就是将当前类的属性编码为NSData类型
- (void)encodeWithCoder:(NSCoder *)aCoder{
// 实际编码过程,原理就是将name这个属性的值编码为NSData类型,因为我们解码的时候,需要重新为该类属性赋值,所以需要加标记,也就是Key。
[aCoder encodeObject:self.name forKey:@"name"];
[aCoder encodeObject:self.gender forKey:@"gender"];
[aCoder encodeInt:self.age forKey:@"age"];
NSLog(@"执行了归档的方法");
}
// 反归档 因为归档的过程中,我们是将当前类转换为NSData类型,并且储存到了某个文件中,当我们从文件中读取出来数据的时候,基础类型,例如:NSArray等都有initWithContentsOfFile的方法来初始化,但是复杂类型没有类似的方法,只能是反归档来完成此事。
- (instancetype)initWithCoder:(NSCoder *)aDecoder{
if (self = [super init]) {
// 将刚才编码为NSData类型的属性,又通过解码方式变回原来的类型,上面编码过程中,所赋给的key值为何种名称,底下的解码得对应上。
self.name = [aDecoder decodeObjectForKey:@"name"];
self.age = [aDecoder decodeIntForKey:@"age"];
self.gender = [aDecoder decodeObjectForKey:@"gender"];
NSLog(@"执行了反归档的方法");
}
return self;
}
第二步、在RootViewController.m文件中导入Person.h文件
#import "RootViewController.h"
#import "SandBoxPaths.h"
#import "Person.h"
@interface RootViewController ()
@end
@implementation RootViewController
#pragma mark -------- 归档
// 归档并存入沙盒中
- (void)archiverAndSaveSandBox{
// 归档实际上就是将Person对象转换为NSData类型的数据
Person *person = [[Person alloc]init];
person.name = @"厦航";
person.age = 24;
person.gender = @"女";
// 归档的时候,实际是将复杂类对象的属性一一转换为NSData类型,所以是逐步转换的,最终需要将每一步转换好的NSData类型组装为一个完整的NSData,所以我们需要一个可变的NSData来接收它
NSMutableData *receiveData = [[NSMutableData alloc]init];
//=========================================================================
// 归档操作需要借助系统的一个归档工具类来实现,这个类实际的操作就是将Person对象转换为NSData类型的数据,并赋值给刚才咱们初始化的NSData对象
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:receiveData];
//=========================================================================
// 归档开始
[archiver encodeObject:person forKey:@"person"];
// 需要有一个标志,让我们知道归档完成了,我们的receiveData中有值了 (不然会出错误)
[archiver finishEncoding];
// 已经转换完成的,就可以进行数据持久化了
NSString *pathString = [[SandBoxPaths documentsPath]stringByAppendingPathComponent:@"person.DA"];
[receiveData writeToFile:pathString atomically:YES];
NSLog(@"-------%@",pathString);
}
#pragma mark ----- 反归档
- (void)unArichiver{
// 反归档,实际上就是将NSData类型转换为复杂类型对象,就是本例中的person对象
NSString *pathString = [[SandBoxPaths documentsPath]stringByAppendingPathComponent:@"person.DA"];
NSData *data = [[NSData alloc]initWithContentsOfFile:pathString];
// 反归档,反归档也需要借助系统的一个反归档工具类来实现
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc]initForReadingWithData:data];
// 开始反归档
Person *person = [unarchiver decodeObjectForKey:@"person"];
NSLog(@"name-------%@",person.name);
}
第三步,在viewDidLoad中调用上面俩个方法。
- (void)viewDidLoad {
[super viewDidLoad];
[self archiverAndSaveSandBox];
[self unArichiver];
}
网友评论