##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];

iOS归档解档 苹果的归档密码_hive

  • ###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);