zoukankan      html  css  js  c++  java
  • iOS--归档和解档(Archiver)、(UnArchiver)

    一、已有类型的归档和解档

    首先来看一个简单的例子:

     //第一方式:归档对象
        //对象-->文件
         NSArray *array = [NSArray arrayWithObjects:@"zhang",@"wangwu",@"lisi",nil];
       
        // NSHomeDirectory 获取根目录 stringByAppendingPathComponent 添加储存的文件名
        
         NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent:@"array.src"];
         BOOL success = [NSKeyedArchiver archiveRootObject:array toFile:filePath];
         if(success){
             NSLog(@"保存成功");
         }else {
             NSLog(@"未保存");
         }
       //  解归档
         array = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
         NSLog(@"%@",array);

     //第二种方式

        //第一种方式的缺陷是一个对象归档成一个文件

        //但是第二种方式,多个对象可以归档成一个文件

         NSArray *array = [NSArray arrayWithObjects:@"zhangsan",@"lisi", nil];

         NSMutableData *data = [NSMutableData data];

         NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];

         //编码

         [archiver encodeObject:array forKey:@"array"];

         [archiver encodeInt:100 forKey:@"scope"];

         [archiver encodeObject:@"jack" forKey:@"name"];

         //完成编码,将上面的归档数据填充到data中,此时data中已经存储了归档对象的数据

         [archiver finishEncoding];

         NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent:@"array.src"];

         BOOL success = [data writeToFile:filePath atomically:YES];

         if(success){

         NSLog(@"归档成功");

         }

        //  对多个对象进行解档操作

        /*

        NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent:@"array.src"];

        //读取归档数据

        NSData *data = [[NSData alloc] initWithContentsOfFile:filePath];

        

        //创建解归档对象,对data中的数据进行解归档

        NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];

        

        //解归档

        NSArray *array = [unarchiver decodeObjectForKey:@"array"];

        NSLog(@"%@",array);

        

        int value = (int)[unarchiver decodeObjectForKey:@"scope"];

        NSLog(@"%d",value);

         */

    • 归档  下面这段代码是将一个NSArray对象写入到一个文件中。
    //对象-->文件
         NSArray *array = [NSArray arrayWithObjects:@"zhang",@"wangwu",@"lisi",nil];
       
        // NSHomeDirectory 获取根目录 stringByAppendingPathComponent 添加储存的文件名
        
         NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent:@"array.src"];
         BOOL success = [NSKeyedArchiver archiveRootObject:array toFile:filePath];
         if(success){
             NSLog(@"保存成功");
         }else {
             NSLog(@"未保存");

    下面代码是创建一个文件的方法

    NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent:@"array.src"];
    • 解档  下面代码是解档就是返回一个对象
    array = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
         NSLog(@"%@",array);
    • 对多个对象进行归档到一个文件
    //第二种方式
        //第一种方式的缺陷是一个对象归档成一个文件
        //但是第二种方式,多个对象可以归档成一个文件
         NSArray *array = [NSArray arrayWithObjects:@"zhangsan",@"lisi", nil];
         NSMutableData *data = [NSMutableData data];
         NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
         //编码
         [archiver encodeObject:array forKey:@"array"];
         [archiver encodeInt:100 forKey:@"scope"];
         [archiver encodeObject:@"jack" forKey:@"name"];
         
         //完成编码,将上面的归档数据填充到data中,此时data中已经存储了归档对象的数据
         [archiver finishEncoding];
         
         NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent:@"array.src"];
         BOOL success = [data writeToFile:filePath atomically:YES];
         if(success){
         NSLog(@"归档成功");
         }

    多个对象归档的话,这里要用到一个类:NSMutableDataNSData,他们两的区别很简单,一个是可变的,一个是不可变的。然后这里还创建了一个归档器:NSKeyedArchiver,这个类负责进行指定类型的编码操作,然后将数据填充到NSMutableData类。归档的时候对每个类型对象用一个key进行对应,这个NSDataNSDirctionary很类似了。

    • 对多个对象进行解档操作
    NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent:@"array.src"];
        //读取归档数据
        NSData *data = [[NSData alloc] initWithContentsOfFile:filePath];
        
        //创建解归档对象,对data中的数据进行解归档
        NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
        
        //解归档
        NSArray *array = [unarchiver decodeObjectForKey:@"array"];
        NSLog(@"%@",array);
        
        int value = (int)[unarchiver decodeObjectForKey:@"scope"];
        NSLog(@"%d",value);

    我们可以将文件解档出一个NSData对象,然后可以通过key去获取指定的类型对象

    二、自定义类型的归档和解档

    上面说到了已有类型的归档和解档,下面来看一下自定义类型的归档和解档操作,在开始的时候也说了,如果自定义的类型可以进行归档和解档的话,必须实现一个协议:NSCoding

    Student.h

    #import <Foundation/Foundation.h>
    
    // 类只有实现NSCoding协议才能归档
    @interface Student : NSObject<NSCoding>
    
    @property(copy,nonatomic)NSString *name;
    @property(assign,nonatomic)int age;
    @property(strong,nonatomic) NSString *adder;
    
    @end

    这里自定义了一个Student类型,实现了NSCoding协议,然后他有三个属性,这里我们看到有新的方法去定义属性

    Student.m

    #import "Student.h"
    
    @implementation Student
    
    // 归档时调用   也是一个初始化
    
    - (instancetype)initWithCoder:(NSCoder *)aDecoder
    {
        NSLog(@"initWithCoder");
        self = [super init];
        if (self!=nil) {
             //一般我们将key定义成宏,这样就不会出错
            _name = [[aDecoder decodeObjectForKey:@"name"] copy];
            self.age = (int)[aDecoder decodeIntegerForKey:@"age"];
            _adder=[aDecoder decodeObjectForKey:@"adder"];
        }
        return self;
    }
    
    // 归档时调用此方法
    - (void)encodeWithCoder:(NSCoder *)aCoder{
        NSLog(@"encodeWithCoder");
        [aCoder encodeObject:_name forKey:@"name"];//一般key和属性名是取一样的
        [aCoder encodeInteger:_age forKey:@"age"];
        [aCoder encodeObject:_adder forKey:@"adder"];
        
    }
    
    // 描述方法
    - (NSString *)description
    {
        return [NSString stringWithFormat:@"name=%@,age=%d,adder=%@", _name,_age,_adder];
    }
    
    @end

    在Person.m文件中,我们需要实现协议中的两个方法:

    initWithCoder

    encodeWithCoder

    这两个方法一个是用于归档操作时会调用的方法,还有一个是用于解档操作时会调用的方法

    1、解档的时候用到的方法

    - (instancetype)initWithCoder:(NSCoder *)aDecoder
    {
        NSLog(@"initWithCoder");
        self = [super init];
        if (self!=nil) {
             //一般我们将key定义成宏,这样就不会出错
            _name = [[aDecoder decodeObjectForKey:@"name"] copy];
            self.age = (int)[aDecoder decodeIntegerForKey:@"age"];
            _adder=[aDecoder decodeObjectForKey:@"adder"];
        }
        return self;
    }

    这个是一个初始化的方法,同时他也是一个解档操作时会调用的方法,所以在这里我们既要写一下初始化方法的特定代码,还要写上解档的代码,这里主要看解档的代码

    其实很简单,就是对属性重新写一下值,然后对每个属性指定一个key就可以了。

    2、归档的时候用到的方法

    // 归档时调用此方法
    - (void)encodeWithCoder:(NSCoder *)aCoder{
        NSLog(@"encodeWithCoder");
        [aCoder encodeObject:_name forKey:@"name"];//一般key和属性名是取一样的
        [aCoder encodeInteger:_age forKey:@"age"];
        [aCoder encodeObject:_adder forKey:@"adder"];
        
    }

    归档和解档的操作正好相反的,但是要注意的是:他们属性的key一定要保持一致

     3、重写description方法

    - (NSString *)description
    {
        return [NSString stringWithFormat:@"name=%@,age=%d,adder=%@", _name,_age,_adder];
    }

    在之前的文章中我说道过,我们在使用NSLog方法打印对象的值的时候,其实是调用对象的description方法,而这个方法是NSObject类中的,我们可以重写他,这样我们就可以打印我们想要的信息了。和Java中的toString方法一样。

    下面就来看一下使用方法了

    #import "ViewController.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        Student *stu=[Student new];
        stu.name=@"张三";
        stu.age=12;
        stu.adder=@"北京";
        
        // 归档
        NSString *filePath=[NSHomeDirectory() stringByAppendingPathComponent:@"message.plist"];
        NSLog(@"%@",filePath);
        BOOL bol=[NSKeyedArchiver archiveRootObject:stu toFile:filePath];
        
        if (bol) {
            NSLog(@"归档成功");
        }else{
            NSLog(@"归档成功");
        }
    
        // 解归档
        Student *stu1=[NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
        NSLog(@"%@",stu1);
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    @end

    我们可以看到,使用起来是很简单的和上面的方式一样,运行结果:

    看到了,我们自定义的description方法,打印了我们自己想要的结果~~

  • 相关阅读:
    Oracle SQL语句大全—查看表空间
    Class to disable copy and assign constructor
    在moss上自己总结了点小经验。。高手可以飘过 转贴
    在MOSS中直接嵌入ASP.NET Page zt
    Project Web Access 2007自定义FORM验证登录实现 zt
    SharePoint Portal Server 2003 中的单一登录 zt
    vs2008 开发 MOSS 顺序工作流
    VS2008开发MOSS工作流几个需要注意的地方
    向MOSS页面中添加服务器端代码的另外一种方式 zt
    状态机工作流的 SpecialPermissions
  • 原文地址:https://www.cnblogs.com/bolin-123/p/5303481.html
Copyright © 2011-2022 走看看