zoukankan      html  css  js  c++  java
  • Runtime应用(三)实现NSCoding的自动归档和自动解档

    当我们需要将一个对象进行归档时,都要让该对象的类遵守NSCoding协议,再实现归档和接档方法。例如有一个Person类,该类有两个成员变量

    @property (nonatomic,copy) NSString *name;
    @property (nonatomic,assign) int age;
    

    两个协议的实现方法如下

    /**
     *  将对象写入某个文件时需要调用,在该方法中说明哪些属性需要存储
     */
    - (void)encodeWithCoder:(NSCoder *)encoder
    {
        [encoder encodeObject:self.name forKey:@"name"];
        [encoder encodeInt:self.age forKey:@"age"];
    }
    
    
    /**
     *  从文件中解析对象时会调用,在该方法中解析对象的属性
     */
    - (id)initWithCoder:(NSCoder *)decoder
    {
        if (self = [super init]) {
            // 解析之后要赋值给属性
            _name = [decoder decodeObjectForKey:@"name"];
            _age = [decoder decodeIntForKey:@"age"];
        }
        return self;
    }

    但当该类拥有上百个属性时,那将会花费更多的功夫在重复代码上,所以使用运行时机制截取类的成员变量,进行赋值

    例如有一个狗类Dog和它的父类动物类Animal

    狗类的成员变量有

    @property (nonatomic,copy) NSString *name;
    @property (nonatomic,assign) int age;

    动物类的成员变量有

    @property (nonatomic,assign) double weight;

    当我们需要将狗对象进行归档时,可以在类中这样重写归档和解档方法

    - (id)initWithCoder:(NSCoder *)aDecoder
    {
       
        if (self = [super init]) {
            Class c = self.class;
            // 截取类和父类的成员变量
            while (c && c != [NSObject class]) {
                unsigned int count = 0;
                Ivar *ivars = class_copyIvarList(c, &count);
                for (int i = 0; i < count; i++) {
                   
                    NSString *key = [NSString stringWithUTF8String:ivar_getName(ivars[i])];
                   
                    id value = [aDecoder decodeObjectForKey:key];
                   
                    [self setValue:value forKey:key];
    
                }
                // 获得c的父类
                c = [c superclass];
                free(ivar);
            }
           
           
        }
        return self;
    }
    
    - (void)encodeWithCoder:(NSCoder *)aCoder
    {
       
         Class c = self.class;
        // 截取类和父类的成员变量
        while (c && c != [NSObject class]) {
            unsigned int count = 0;
           
            Ivar *ivars = class_copyIvarList(c, &count);
           
            for (int i = 0; i < count; i++) {
                Ivar ivar = ivars[i];
                NSString *key = [NSString stringWithUTF8String:ivar_getName(ivar)];
    
                id value = [self valueForKey:key];
               
                [aCoder encodeObject:value forKey:key];
            }
            c = [c superclass];
            // 释放内存
            free(ivar);
        }
       
    }

     代码测试:

    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {
        CXDog *d = [[CXDogalloc] init];
        d.name = @"cx";
        d.age = 12;
        d.weight = 1.55;
        // 将对象归档
        [NSKeyedArchiverarchiveRootObject:d toFile:@"/Users/c_xie/Desktop/wj.xxoo"];
        // 将对象解档
        CXDog *dog = [NSKeyedUnarchiverunarchiveObjectWithFile:@"/Users/c_xie/Desktop/wj.xxoo"];
        NSLog(@"%@,%d,%f",dog.name,dog.age,d.weight);
       
    }

    以后就算有再多的属性,一个循环搞定

  • 相关阅读:
    使用RedisDesktopManager客户端无法连接Redis服务器问题解决办法
    centos7 安装postgresql11
    CentOS7安装MySQL(完整版)
    【Linux】CentOS7下安装JDK详细过程
    用FastDFS一步步搭建文件管理系统
    ELK教程3:logstash的部署、SpringBoot整合ELK+Filebeat
    ELK教程2:Kibana的安装
    ELK教程1:ElasticSearch集群的部署ELK
    设置侧边栏动态漫画
    Kubernetes中的workload(工作负载)
  • 原文地址:https://www.cnblogs.com/junhuawang/p/5798827.html
Copyright © 2011-2022 走看看