数据持久化——复杂对象写入文件(归档和反归档(解档))

由于复杂对象无法通过writeToFile:方法进行数据持久化,只能通过将复杂对象转换为NSData,通过writeToFile;进行数据持久化。
将复杂对象转换为NSData,通过归档;将NSData转换为复杂对象,通过反归档。

这里使用归档和反归档的时候需要在.h文件中导入一个协议协议,注意这个协议比较特殊不需要指定代理对象。

第一步、导入代理实现他的俩个代理方法
Person.h


@interface Person : NSObject 

@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];
}

你可能感兴趣的:(数据持久化——复杂对象写入文件(归档和反归档(解档)))