自从做iOS端心电SDK以来,已经一年基本没有接触网络请求。最近由于SDK需求的改变需要解析网络数据,这就难免要解析网络请求返回的Json数据。
我们知道Json数据转Model对象是由Json先转换为NSDictionary对象,再转换为model对象的。这个过程成熟的框架有JSModel,YYModel,MJExtension等等,但是如果只是用于NSDictionary转Model不想用这些框架怎么办?
NSDictionary转Model对象的方式有两种,KVC方式和Runtime方式。前者是遍历字典中所有key,去模型中查找有没有对应的属性名然后赋值;后者刚好相反,遍历模型中所有属性名,去字典中查找然后赋值。那为什么我们提倡用Runtime方式呢?
Runtime:iOS的黑魔法啊,这样写显得多有逼格!!!其实,实际的好处还是有的,Runtime方式相比JSModel等减少了大量不必要的代码,而且接近底层的实现使得效率更高。当然,逼格高还是最重要的理由,没有之一!
Model本质上是一个对象,所有的OC对象又都继承自NSObject。所以我们给NSObject新建一个分类来实现NSDictionary转Model。
1.新建一个NSObject的分类chDic2Model(在新建类和分类时最好给类名加一个属于你自己的前缀,因为OC不像C++,JAVA等有namespace的概念!当然,如果你的代码永远只能被你自己使用到,也可不必多此一举[baiyan...])
2.首先写一个获取当前类属性的方法propertyList,由于这里用到了Runtime,记得先引入头文件:#import<objc/runtime.h>
3.接下来就可以写NSDictionary转Model的对外接口了:
现在,这个工具就基本成型了。可以写个Demo来跑一下了。
先建一个Model类,然后在主视图里模拟一个json数据的字典,进行模型转化:
怎么样,是不是觉得很简单,而且代码量也很少就解决了问题。那么问题来了,作为一个强迫症患者兼有着良好编码习惯的码者,实在不想在自己的代码里看到score_art这样的命名。
4.属性名与字典key值不同时怎么破???(划难点啦)
首先要知道要求model属性名与字典key值相同,是为了在KVC赋值时一一对应。name我们先建立一个与属性名有一一映射关系的中间表,使得该表字段和字典分别对应相等即可。
首先,新建一个函数用于返回Model属性名和字典key值得映射关系,然后优化字典转模型接口的实现
接着将模型不符合命名规则的属性名改为驼峰命名,在.m文件中重写属性映射关
接下来,就可以跑起来试试了。
怎么样?这下可有一点成就感了吧。我都码类了,但是还有一个问题不知道大家有没有注意到。我们在用JSModel时,关于上述问题的处理方式大致相同。但是在对象属性名映射时,有些与字典key相同的字段就没必要写出来了。这样做确实不错,因为万一属性很多的话,这样写下去真心有点D疼。那么我们这个工具也能不能像JSModel那样处理呢?
这也是我遇到的一个比较棘手的问题,因为字典转模型的实现是写在NSObject的分类里。这个时候我根本知不道将要定义的子类里哪个字段和对应字段key值不同,我只能都按照不同的方式建立一个映射,在KVC赋值的时候才拥有完整的属性。这个下午的这个问题真是百思不得其姐哈......
这里这个属性名,字段key处理起来挺绕的,当时可能饶了弯路。现在想想其实也不是很难,仔细理清思路就简单多了。映射字典里是属性名和字典key不一致的字段,可以copy一份带转化字典,然后根据映射关系把copy的那份字典里的key对应的值按映射关系转移到新字典,同时把转移了的字段删除,那么剩下的就是属性名和字典key一致的字段了,直接追加到新字典里就可以了。这样得到的新字典就是key值与Model属性名一致的字典,而且字典的value值都是转化自原始字典。(我嚓,写笔记的时候恍然里头冒出个大悟来:这么简单,比我下午采取的方式简单多了。PS:做笔记总结对思路启发还是挺管用的哈!!!)
原来,代码实现是一回事。写成总结性的笔记又是一回事,在写笔记的同时既巩固了既有知识,又能时不时在原有代码的基础上有新的启发。作为一枚超低级的iOS开发,希望能在码笔记的路上码海无涯回头无岸,学习使人快乐!
如果你有任何关于本文的问题或建议,可以在文末留言,我们一起学习交流。也可以加扣扣(995955216)微信(同qq)索要源代码Demo。
--20171019夜
-------------------------------------------------------------------------------------