zoukankan      html  css  js  c++  java
  • iOS之序列化与反序列化

    所谓的序列化和反序列化就是将数据结构或对象和二进制串之间相互转换的过程;

    本人的理解是当你于写数据需要本地存储时,即将你的数据写到硬盘上的时候,你就必须对他进行序列化,转换成二进制文件,从而便于在磁盘上的读写,同理在取出的时候必须将其在反序列化,这样才能将数据读出来,就好比加密和揭秘的过程。

    在ios应用中如果需要保存大对象数据可以采用xml文件或者属性文件方式,但由于采用的纯文本方式保密性不够,如将保存数据封装为自定义类的实例通过序列化的二进制方式进行保存,这样安全性会有所提高。

    具有序列化能力的类必须实现NSCoding协议的两个函数:

    -(void) encodeWithCoder:(NSCoder *)encoder;

    -(id) initWithCoder:(NSCoder *)decoder;

    需求:使用NSUserDefaults存储对象,比如登录的时候直接把用户的信息转对象存储到本地。等要用的时候在拿出来用。但是NSUserDefaults并不能存储对象,所以要把对象进行序列化和反序列化。转为二进制进行存储。

    以下附上代码实例:

    对象模型.h文件声明的属性:

    @property (nonatomic , copy) NSString *name; 

     对象模型.m文件实现的序列化与反序列化方法

    //实现序列化和反序列化
    - (void)encodeWithCoder:(NSCoder*)aCoder{
        [aCoder encodeObject:self.name forKey:@"name"];
    }
    
    - (id)initWithCoder:(NSCoder*)decoder{
        if (self= [super init])
        {
            if (decoder == nil)
            {
                return self;
            }
            self.name= [decoder decodeObjectForKey:@"name"];
        }
        return self;
    }
    

     以下是生成对象、序列化存储、反序列化读取的过程:

    // 自定义对象存储
        WFModel *model = [[WFModel alloc] init];
        model.name = @"咿呀呀";
    
        //存储
        NSData *data = [NSKeyedArchiver archivedDataWithRootObject:model];
        [[NSUserDefaults standardUserDefaults] setObject:data forKey:@"model"];
        
        //读取
        NSData *deData = [[NSUserDefaults standardUserDefaults]objectForKey:@"model"];
        WFModel *deStu = [NSKeyedUnarchiver unarchiveObjectWithData:deData];
        NSLog(@"deStu---%@",deStu.name);

    ------success------

    2019-2-22 补充一种新的序列化方式,之前是常规的方式,现在的是利用runtime实现的

    首先声明头文件

    #import<objc/runtime.h>

    - (void)encodeWithCoder:(NSCoder *)coder
    {
        NSLog(@"实现codeing协议");
        //告诉系统归档的属性是哪些
        unsigned int count = 0;//表示对象的属性个数
        Ivar *ivars = class_copyIvarList([BaseModel class], &count);
        for (int i = 0; i<count; i++) {
            //拿到Ivar
            Ivar ivar = ivars[i];
            const char *name = ivar_getName(ivar);//获取到属性的C字符串名称
            NSString *key = [NSString stringWithUTF8String:name];//转成对应的OC名称
            //归档 -- 利用KVC
            [coder encodeObject:[self valueForKey:key] forKey:key];
        }
        free(ivars);//在OC中使用了Copy、Creat、New类型的函数,需要释放指针!!(注:ARC管不了C函数)
    }
    
    
    - (instancetype)initWithCoder:(NSCoder *)coder
    {
        self = [super init];
        if (self) {
            //解档
            unsigned int count = 0;
            Ivar *ivars = class_copyIvarList([BaseModel class], &count);
            for (int i = 0; i<count; i++) {
                //拿到Ivar
                Ivar ivar = ivars[i];
                const char *name = ivar_getName(ivar);
                NSString *key = [NSString stringWithUTF8String:name];
                //解档
                id value = [coder decodeObjectForKey:key];
                // 利用KVC赋值
                [self setValue:value forKey:key];
            }
            free(ivars);
        }
        return self;
    }
    

    //注:使用runtime的好处不言而喻,无论对象有多少属性都可以通过这个for循环搞定,非常棒。

    然后就可以的愉快的玩耍啦

  • 相关阅读:
    操作系统演进和未来趋势(附下载)
    用树莓派构建一台服务器,永久运行网站
    用 Docker 构建 MySQL 主从环境
    (一)多线程:线程概述
    网站可访问性的五个自动化测试工具
    个人对前端工程化的理解
    MongoDB安装过程中出现service MongoDB failed to start,verify that you have sufficient privileges to start
    前端开发IDE
    atom插件:js,nodejs,es6补全,高度定制化
    atom离线手动安装atom插件
  • 原文地址:https://www.cnblogs.com/110-913-1025/p/8898066.html
Copyright © 2011-2022 走看看