美文网首页iOS 程序员iOS进阶之路iOS 大神之路
Runtime使用场景 - 序列化和反序列化

Runtime使用场景 - 序列化和反序列化

作者: ArchLL | 来源:发表于2017-07-21 12:25 被阅读122次

    Runtime 有什么用?

    1. 利用Runtime运行时,在程序的运行过程中,动态创建一个类
    2. 利用Runtime运行时,在程序运行中动态修改一个类的属性/方法
    3. 利用Runtime运行时,遍历一个类的所有属性和方法

    这里来介绍一下怎么利用在Runtime运行时,通过遍历一个类的所有属性来实现序列化和反序列化

    注:这里讲的是复杂对象的归档,基本数据类型的归档这里暂不做介绍

    相比常规写法的优点:
    1. 快捷,一般开发中模型的属性非常多,如果用常规的方法,需要逐个进行编码反编码,想想就痛苦
    1. 省心,不用去管每个属性的类型
    2. 省事,代码可复用,新建模型的时候,可直接复用这两端段编码反编码这两段代码,只用在一处修改模型名称即可
    效果示例

    代码示例:对Person的属性进行编码和反编码(先遵循NSCoding协议)

    1.编码
    //编码
    - (void)encodeWithCoder:(NSCoder *)aCoder {
      //常规写法
        /*
        [aCoder encodeObject:_name forKey:@"name"];
        [aCoder encodeObject:_gender forKey:@"gender"];
        [aCoder encodeInteger:_age forKey:@"age"];
        */
     //Runtime写法
       //1.导入头文件 <objc/message.h>
       //2.获取这个类的所有成员变量列表的指针列表(这个可以在程序的任何地方获取,获取的成员变量包括这个类的私有属性)
        unsigned int count = 0;
        //c语言里面,如果传递一个基本数据类型的指针,那一般都是需要在函数内部修改它的值!
        Ivar * ivars = class_copyIvarList([Person class], &count);
        for (int i = 0; i< count; i++) {
            //拿出属性的名称
            Ivar ivar = ivars[i];
            const char * name = ivar_getName(ivar);
            //C语言字符串转化为OC字符串
            NSString * KEY = [NSString stringWithUTF8String:name];
            //取出属性对应的值 KVC
            id value = [self valueForKey:KEY];
            //编码
            [aCoder encodeObject:value forKey:KEY];
        }
        //注意:C语言里面需要释放指针
        free(ivars);
    }
    
    
    2.反编码
    //反编码
    - (instancetype)initWithCoder:(NSCoder *)aDecoder {
        self = [super init];
        if (self) {
            //常规写法
            /*
            _name   = [aDecoder decodeObjectForKey:@"name"];
            _gender = [aDecoder decodeObjectForKey:@"gender"];
            _age    = [aDecoder decodeIntegerForKey:@"age"];
            */
            //runtime写法
            unsigned int count = 0;
            Ivar * ivars = class_copyIvarList([Person class], &count);
            for (int i = 0; i< count; i++) {
                //获取属性的名称
                Ivar ivar = ivars[i];
                const char * name = ivar_getName(ivar);
                //C语言字符串转化为OC字符串
                NSString * KEY = [NSString stringWithUTF8String:name];
                //反编码
                id value = [aDecoder decodeObjectForKey:KEY];
                //将值设置到对应的属性上 KVC
                [self setValue:value forKey:KEY];
            }
            //注意:C语言里面需要释放指针
            free(ivars);
        }
        return self;
    }
    
    

    归档和反归档

    1.归档
    //归档路径
    - (NSString *)getFilePath{
        //注:这里存储的是二进制类型的数据,故文件后缀名随便写
        return  [NSTemporaryDirectory() stringByAppendingPathComponent:_FileName];
    }
    
    //归档(序列化)
    - (IBAction)archiveAction:(id)sender {
        Person *per = [[Person alloc]init];
        per.name   =  @"Jack";
        per.age    =  20;
        per.gender =  @"man";
        //设置文件名 注:这里存储的是二进制类型的数据,故文件后缀名随便写
        _FileName = [NSString stringWithFormat:@"%@%@",per.name,@".per"];
        //归档
        [NSKeyedArchiver archiveRootObject:per toFile:[self getFilePath]];
        //检测是否归档成功
        BOOL result = [[NSFileManager defaultManager] fileExistsAtPath:[self getFilePath]];
        if (result) {
            [SYProgressHUD showSuccessText:@"序列化成功"];
        }else{
            [SYProgressHUD showFailureText:@"序列化失败"];
        }
    }
    
    2.反归档
    //反归档(反序列化)
    - (IBAction)unarchiveAction:(id)sender {
        //解档
        Person *per = [NSKeyedUnarchiver unarchiveObjectWithFile:[self getFilePath]];
        //显示读取的文件
        _showReadInfoLB.text = [NSString stringWithFormat:@"name: %@  gender: %@  age: %ld",per.name,per.gender,per.age];
        NSLog(@"%@",_showReadInfoLB.text);
    }
    
    具体代码请前往:https://github.com/ArchLL/ARRuntime 欢迎Star

    相关文章

      网友评论

        本文标题:Runtime使用场景 - 序列化和反序列化

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