WLFModel

来源:互联网 发布:java class.this 编辑:程序博客网 时间:2024/06/08 15:10

最近真是忙的一逼,程序员和产品真的是死对头,公司新来两个产品,本来项目紧,需求改这样,又改那样。不管是iOS还是Android都对他们发了脾气。我也有句“妈卖批”想对他们说。

  • YYModel的基本流程
  • WLFModel的使用
  • WLFPropertyInfo的定义
  • WLFClassInfo的定义
  • modelWithDictionary
  • objc_msgsend的用法
  • 执行结果

YYModel的基本流程

在工作中一直是使用YYModel来将Json转换成model, 确实很好用,虽然知道和runtime有关,但是从没有看过内部的代码。因为我还很菜,没有阅读别人代码的能力。。不过最后还是硬着头皮看了点,有了点眉目。

老实说,其实我还是没有完全读懂,不过基本流程还算清楚。经过我的总结,YYModel的基本流程,约有以下几步:

  1. 使用的时候先调用modelWithJson,在内部将Json字符串,转换成NSDictionary,然后调用modelWithDictionary
  2. 如果存在相关类信息的缓存,则取缓存信息,否则,调用initWithClass方法,获取到类的方法、属性等信息,同时写入缓存
  3. 如果有实现modelPropertyWhiteList、modelPropertyBlackList、modelContainerPropertyGenericClass等方法,则相应的做处理,添加到对应的数据结构
  4. 沿继承链获取到属性对应的方法,如getter, setter,直达根对象
  5. 调用modelSetWithDictionary,根据model信息,调用setter方法,设置相关值。

粗略流程就是这样,根据YYModel,我自己也想尝试写一个,当然比不起大神写的,但是谁没有一个辣鸡的过程呢?写这个并不为实际使用,仅为学习和娱乐。

WLFModel的使用

首先根据使用的方法,同样的,按照YYModel的使用方法,用Json字符串做为输入。内部同样将Json转换成NSDictionary,再调用modelWithDictionary方法:

首先定义数据的类型编码和属性编码,如下所示:

关于属性的编码,请参见网址:Property Type String
关于类型编码请参见网址:Type Encodings

WLFPropertyInfo的定义

先定义属性信息类WLFPropertyInfo,定义如下:

其中,包含一个属性名称propertyName,属性对应的变量variableName,类型编码typeEncoding,getter方法getterMethod,setter方法setterMethod,属性列表attributeList。

objc_property_attribute_t结构的定义如下所示:

/// Defines a property attributetypedef struct {    const char *name;           /**< The name of the attribute */    const char *value;          /**< The value of the attribute (usually empty) */} objc_property_attribute_t;

其中name,表示属性编码,value表示结果值。

如果用户有自定义的getter方法,则根据上述描述,name为’G’, value是getter方法名。同理setter也一样,如上例,自定义了getter方法getUserName,则objc_property_attribute_t的name字段值为’G’, value字段值为’getUserName’。如下图所示:

在获取属性编码的时候,如果传入的类型不是普通数据类型,而是类数据类型,那么将会以组合字符串的形式给出,即可从中截取出对象类型。如下图所示:

WLFClassInfo的定义

接下来,我们获取类的信息,由于只是粗略的编码,我们只获取类中与属性相关的信息, 其他的一概不论。

其中,包括当前类和父类的Class,当前类名className,是否元类isMetaClass,属性信息列表,父类信息superClassInfo。

在这里,我们递归获取类及父类的信息,直到NSObject为止,YYModel在这一步里增加了缓存机制,大大提高了效率。

modelWithDictionary

最后,我们来设置对应属性的值,首先,我们构建我们需要获取到对应的属性名,由于Json中的属性可能位于父类中,所以我们需要递归查找,直至NSObject,代码如下所示:

在获取的过程中,构建对应属性的setter方法,如果没有自定义的setter方法,则大写属性名的首字母,添加set字符串。然后根据类型编码的不同,设置对应的值。如下所示,针对不同的数据类型,给对应属性的setter方法发送消息。

objc_msgsend的用法

objc_msgsend的原型如下所示,参见objc/message.h:

OBJC_EXPORT id objc_msgSend(id self, SEL op, ...)    OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0);

在使用的时候,我们需要使用强制转换,将该函数转换成对应的数据类型,如上图所示。

同时,如果需要使用objc_msgsend,需要进行以下一步设置:
BuildSettings-ENABLE_STRICT_OBJC_MSGSEND 将YES修改为NO
操作如下:

执行结果

最终的执行结果如下所示:

该代码仅为学习YYModel而编写,并非用做实际项目,请勿喷,谢谢。。

原创粉丝点击