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方法,打印了我们自己想要的结果~~

  • 相关阅读:
    python json 访问与字符串截取
    python 12306 车次数据获取
    12306 城市代码 切片技巧
    python 9*9 乘法表
    python 列表转为字典的两个小方法
    python 三种遍历列表里面序号和值的方法
    虚拟机中访问连接在物理机上的摄像机(使用桥接)
    C++程序调用python3
    Notepad++编写运行python程序
    查看进程被哪台电脑的哪个进程连接(netstat)
  • 原文地址:https://www.cnblogs.com/bolin-123/p/5303481.html
Copyright © 2011-2022 走看看