关于归档/解档(序列化/反序列化)

在昨天看了一个视频,讲解的是归档和解档,也就是“序列化”和“反序列化”。觉得自己所学知识真是太少了!!底层的东西懂得几乎为zero。看了就要记下来,就要去理解,去消化,这是学习,成长的必经之路。虽然辛苦,但是值得。因为,在这其中你可以有很多的乐趣,可以沉浸在里面,感觉很舒服。。。
言归正传:你知道数据持久化的方式有哪几种吗?你猜。。

什么是Serialization (序列化)?

写数据到本地磁盘或者进行传输时,需要进行序列化,转化成二进制流,从而便于传输和存储。同理,得到二进制流后,需要进行反序列化,还原成可以使用的数据。
需要注意的是,不同的环境,serialize和unserialize是不同的。一般同一环境中的操作才能得到正确的数据。

接下来是进行归档的代码:

友情提示:请同学们导入头文件 <objc/message.h>!!!

归档的代码:

//归档
[NSKeyedArchiver archiveRootObject:@"归档的内容" toFile:filePath];  
/*归档的内容可以是任意格式和内容*/

还需要给归档的内容一个存储的路径,另外还可以添加一个后缀名,比如:.txt、.exe、.han、.我的、.dog、.person。。。。就是说,后缀随便自己设置即可(是不是挺好滴呢,想说没说的都可以加上,哼哼)
创建文件并归档:外部设置

Dog *dog = [[Dog alloc] init];
dog.color = @"黑色";
dog.age = 3;
//文件路径:保存一个临时文件
NSString *tempPath = NSTemporaryDirectory();
//后缀名给了一个.dog
NSString *filePath = [tempPath stringByAppendingPathComponent:@"myDog.dog"];
//归档
[NSKeyedArchiver archiveRootObject:dog toFile:filePath];

到这里,有同学就问了:NSTemporaryDirectory()这个方法干甚用滴?创建的是临时文件!!!

获取路径的代码可以直接在viewDIdLoad里面就可以了,代码:

//打印输出临时文件路径
NSLog(@"%@", NSTemporaryDirectory());

给同学们看一下返回的路径(模拟器上):


临时文件路径
那么 stringByAppendingPathComponent 为什么要选择这个呢?当然是为了偷懒不用添加"/"了,哼哼。。
现在你就可以去访问文件了 command+shift+G ,粘贴路径,回车!!!别跟我说你这都不会!你创建的这个文件,什么工具都打不开,只有你自己可以打开:进行 解档(反序列化)。
文件

我创建了一个Dog类,并且赋予它两个属性:

//年龄
@property (nonatomic, assign) NSInteger age;
//颜色
@property (nonatomic, copy) NSString *color;

在外部调用的调用的时候就比较简单了:
ViewController.m中代码:归档(序列化)的已经在上面写过了,接下来是解档(反序列化):外部调用

//文件路径:保存一个临时文件,解档时候当然要获取文件啦
NSString *tempPath = NSTemporaryDirectory();
NSString *filePath = [tempPath stringByAppendingPathComponent:@"myDog.dog"];
//解档
Dog *dog = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
NSLog(@"我的小狗今年%ld岁,它毛是%@的", (long)dog.age, dog.color);

输出的结果(有图有真相):

解档后
那么问题来了:在Dog类里面是怎么写的呢?问得好!请同学们看下面的精彩之处!!
- (void)encodeWithCoder:(NSCoder *)aCoder {
    [aCoder encodeInteger:_age forKey:@"age"];
    [aCoder encodeObject:_color forKey:@"color"];
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super init]) {
        _color = [aDecoder decodeObjectForKey:@"color"];
        _age = [aDecoder decodeIntegerForKey:@"age"];
    }
    return self;
}
是否有同学又要问了:如果这只小狗比较牛B,有10个、20个属性呢?难道要这样写20几个归档解档代码吗?太low了吧?问得好!那么怎么解决该问题呢?用 RunTime!!!对!你没听错,是他,是他,就是他!!
归档:Dog.m
- (void)encodeWithCoder:(NSCoder *)aCoder {
    //count是什么意思呢?
    unsigned int count = 0;
    Ivar *ivars = class_copyIvarList([Dog class], &count);
    for (int i = 0; i < count; i ++) {
        //所有的成员属性
        Ivar ivar = ivars[i];
        //那都属性的名称
        const char *name = ivar_getName(ivar);
        //设置key
        NSString *key = [NSString stringWithUTF8String:name];
        //通过KVC归档
        [aCoder encodeObject:[self valueForKey:key] forKey:key];
    }
    //class_copyIvarList是c语言,需要手动管理内存。
    free(ivars);
}
下面对代码解析一下:
(1)class_copyIvarList(<#__unsafe_unretained Class cls#> , <#unsigned int ***outCount#> )

获取某类的所有属性列表,包括@property{ } 中设置的属性。顺便说一下: class_copyPropertyList 则是只有 @property 声明的属性。

点进去之后的方法显示:里面的参数type需要在外面进行设置。

(2)OBJC_EXPORT Ivar ***class_copyIvarList(Class cls, unsigned int *outCount)

返回的类型是:Ivar*,即用“Ivar *”接受数组(属性列表)。
看一下count的类型:unsigned int * outCount,获取到的是属性的个数。unsigned int count = 0;

//下面的打印输出属性个数:
class_copyIvarList(NSClassFromString(@"Dog"), &count);
NSLog(@"Dog属性个数:%d", count);
(3) Ivar ivar = ivars[i];遍历数组中的ivar,为何没有 * 了呢?附加一篇:Ivar

**typedef struct objc_ivar *Ivar; **这是一个结构体!!!

(4)const char *name = ivar_getName(ivar);

请看过OBJC_EXPORT const char *ivar_getName(Ivar v),里面的参数就是没有 * 的哦。获取的是每一个属性。
我们都明白的一个事情是:归档之后就是UTF8格式的啦,获取属性就相当于其中的key。

(4)我们找到了key,那么value不就好弄了吗,通过KVC,欧耶,归档成功!!!!

注意:一定要释放!!因为他是C,手动管理是必须的。 free(ivars);

解档:Dog.m
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super init]) {
       //count是什么意思呢?
        unsigned int count = 0;
        Ivar *ivars = class_copyIvarList([Dog class], &count);
        for (int i = 0; i < count; i ++) {
            //所有的成员属性
            Ivar ivar = ivars[i];
            //那都属性的名称
            const char *name = ivar_getName(ivar);
            //设置key
            NSString *key = [NSString stringWithUTF8String:name];
            //利用KVC解档
            id value = [aDecoder decodeObjectForKey:key];
            [self setValue:value forKey:key];
        }
        //class_copyIvarList是c语言,需要手动管理内存。
        free(ivars);
    }
    return self;
}

解档没有什么可说的,跟上面归档的节奏基本是一样的,就是记得解档之后的类型是任意的 id 类型,然后利用KVC进行赋值。[self setValue:value forKey:key];即可将其反序列化。
我们使用这些东西可以干什么呢?答:建模型!没错,创建Model。

Runtime的特点是什么?附上一个链接:RunTime

(1)动态创建类。
(2)动态添加属性、方法。
(3)消息机制。

Dog *dog = [[Dog alloc] init];
//一个food方法
[dog foods];
[dog performSelector:@selector(speed) withObject:nil];
//方法名
NSLog(@"%s", __func__);
//消息传递机制
objc_msgSend(dog, @selector(speed));
//消息传递机制
objc_msgSend(dog, sel_registerName("foods"));

以上是简单的对RunTime的使用和理解。以上的链接可以有所帮助。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,783评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,360评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,942评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,507评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,324评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,299评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,685评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,358评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,652评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,704评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,465评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,318评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,711评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,991评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,265评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,661评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,864评论 2 335

推荐阅读更多精彩内容