美文网首页UI笔记
数据持久化——复杂对象写入文件(归档和反归档(解档))

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

作者: 蛐蛐_ | 来源:发表于2015-12-16 20:33 被阅读214次

    由于复杂对象无法通过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];
    }
    

    相关文章

      网友评论

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

      本文链接:https://www.haomeiwen.com/subject/wrfphttx.html