##1、数据归档(Archive)
使用属性列表可以持久化数据,但是这种保存的方式是明文的不能达到文件的隐秘性。iOS中还提供了一种持久化的方法叫做数据归档,使用 NSKeyedArchiver
(归档) 和 NSKeyedUnarchiver
(解归档)类完成。这种方式可以对数据进行编码为二进制的形式保存,从而达到数据的隐秘性。要归档的数据必须实现**<NSCoding>
协议,<NSCoding>协议包含encodeWithCoder:
**编码方法 和 **initWithCoder:
**解码方法。
- ###1.1 常用Foundation类的数据归档 常用的Foundation类都实现了<NSCoding>协议,所有可以直接归档,包含可变类型。归档的过程就是将数据进行编码保存,使用 NSKeyedArchiver 进行编码归档。
//1、创建文件保存路径
NSString *dicPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *filePath = [dicPath stringByAppendingPathComponent:@"data.archive"];
//2、设置保存的数据
NSMutableArray *infos = [NSMutableArray array];
[infos addObject:@"One"];
[infos addObject:@100];
[infos addObject:[NSDate date]];
//3、将数据归档到指定路径
[NSKeyedArchiver archiveRootObject:infos toFile:filePath];
- ###1.2 常用Foundation类的数据解归档 解档就是将编码的数据进行反编码为原来的类型数据,使用 NSKeyedUnarchiver 完成解档。
NSMutableArray *objs = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
NSLog(@"%@",objs);
- ###1.3自定义的对象归档 有时候我们需要本地保存自己定义的一些对象数据,这些对象并没有实现<NSCoding>协议,所以在归档数据前要先去实现<NSCoding>协议中的方法,在协议方法中对自定义对象属性的编码和解码。如下实现自定义的User类对象的归档:
1、.h中设置属性并实现<NSCoding>协议
@interface User : NSObject <NSCoding>
@property(assign, nonatomic) NSInteger userID;
@property(copy, nonatomic) NSString *userName;
@property(copy, nonatomic) NSString *userPassword;
@end
2、.m文件中实现协议方法,encodeWithCoder: 和 initWithCoder:完成对属性数据的编码和解码。
// 给数据编码
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeInteger:_userID forKey:@"userID"];
[aCoder encodeObject:_userName forKey:@"userName"];
[aCoder encodeObject:_userPassword forKey:@"userPassword"];
}
// 给数据解码
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super init]) {
self.userID = [[aDecoder decodeObjectForKey:@"userID"] integerValue];
self.userName = [aDecoder decodeObjectForKey:@"userName"];
self.userPassword = [aDecoder decodeObjectForKey:@"userPassword"];
}
return self;
}
3、将自定义对象归档到指定文件路径中
// 设置路径
NSString *dicPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *filePath = [dicPath stringByAppendingPathComponent:@"user"];
// 创建对象设置数据
User *user = [[User alloc] init];
user.userID = 1000001;
user.userName = @"kingde";
user.userPassword = @"123456789";
// 归档自定义对象,归档会调用encodeWithCoder:方法
[NSKeyedArchiver archiveRootObject:user toFile:filePath];
- ###1.4 自定义的对象解归档
// 解档
User *userData = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
NSLog(@"user:%@",userData);
- ###1.5 将数据转为NSData归档
归档数据时可以直接将该类型数据归档,也可以将这些类型的数据编码为NSData类型的数据后再进行持久保存(NSData保存的是二进制的数据)。
NSKeyedArchiver的**archivedDataWithRootObject:
**:方法将对象数据编码为NSData类型数据。
NSKeyedUnarchiver的**unarchiveObjectWithData:
**:方法将NSData类型数据解码为原类型数据。
NSString *dicPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *filePath = [dicPath stringByAppendingPathComponent:@"object"];
User *user = [[User alloc] init];
user.userID = 1000002;
user.userName = @"kitty";
user.userPassword = @"98754321";
// 1、使用NSKeyedArchiver将自定义的对象数据编码为NSData对象
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:user];
// 2、写入数据到指定路径中
[data writeToFile:filePath atomically:YES];
// 3、获取保存的NSData数据
NSData *objData = [NSData dataWithContentsOfFile:filePath];
// 4、将NSData数据解码为自定义的对象
User *userObj = [NSKeyedUnarchiver unarchiveObjectWithData:objData];
NSLog(@"%@",userObj);