【iOS】——YYModel源码总结
性能优化及优点
YYModel主要用于将JSON数据转换为模型对象,以及将模型对象转换为字典的库。相比于其他的数据转换库例如JSONModel,它更加的轻量级并且性能更高,因为它在很多地方做了优化:
- 通过
CFDictionaryCreateMutable
方法将数据存入缓存,需要使用的时候直接拿出,就不用重复解析类,该方法是C语言,相比于JSONModel使用关联对象进行缓存省去了OC的消息发送,性能更高。 - 并且通过getter和setter方法用JSON数据给模型的属性进行赋值而不是像JSONModel通过kvc赋值从而提高性能。因为前者可以利用编译时优化、静态类型检查以及直接访问底层实例变量。而KVC需要在运行时进行更多的动态查找和类型检查。
- 在内存管理中大量使用__unsafe_unretained而不是__strong和__weak因为
__unsafe_unretained
仅涉及简单的指针赋值操作,完全避免了引用计数的增减开销及相关的内存管理和同步操作,因此性能更高。但使用时必须非常小心以避免产生悬垂指针问题。因为__unsafe_unretained指针指向的对象被释放后指针不会置nil还是指向原来的地址,但是该地址的内容已经被释放,访问的话存在安全性问题。(野指针通常指向从未有效分配的内存,而悬垂指针曾有效但对象已被销毁或内存已被释放。) - 在处理键值映射和类型转换时,会用到如
YYClassIvarInfo
、YYClassMethodInfo
这样的C结构体来存储有关ivar和方法的信息,然后通过纯C函数来操作这些结构体,避免了频繁的ObjC方法调用。 - 减少遍历的循环次数,在
JSON
和Model
转换前,Model
的属性个数和JSON
的属性个数都是已知的,这时选择数量较少的那一方进行遍历,会节省很多时间
YYModel的容错性更好,它会自动进行错误类型检查,如果检查到不匹配的类型会自动赋值为nil。
YYModel无侵入性,它采用类别的方式来实现功能,不同于JSONModel需要模型类继承于JSONModel类
使用注意
对于非容器类属性直接进行转换就行,对于容器类属性,需要指定容器类属性中元素的数据类型,因为容器类例如NSArray和NSDictionary都是类型无关的,如果不指定容器中的元素类型,YYModel就不知道该将JSON数据转换成什么类型的对象
通过modelContainerPropertyGenericClass 方法来制定容器内的元素类型
#import "TestYYModel.h"
@implementation TestYYModel
// 必须要在这个方法中告诉数组类型
+ (NSDictionary *)modelContainerPropertyGenericClass { // 容器类属性没有注明元素属性所属类别
return @{@"stories" : [Story class], @"top_stories" : [TopStory class]};
}
@end
架构分析
结构分为两个部分:NSObject+YYModel、YYClassInfo
YYClassInfo
主要将Runtime 层级的一些结构体封装到NSObject
层级以便调用。例如其中的YYClassIvarInfo是对objc_ivar的封装(包含变量名、变量类型、变量偏移量等)、YYClassMethodInfo是对objc_method的封装(包含方法名和方法指针)、YYClassPropertyInfo是对property_t的封装(包含属性名、属性类型、属性相关协议、getter和setter的方法指针)、YYClassInfo是对objc_class的封装(包含了类名、父类指针、类遵循的协议等)NSObject+YYModel
主要负责处理转换的逻辑以及提供接口 这里面转换的逻辑基本上都是用到了YYClassInfo
中封装的Runtime
结构体
流程分析
- 首先JSON数据通过yy_modelWithJSON方法转换为NSDictionary对象,这里的JSON数据格式可以是NSString、NSData、NSDictionary类型
- 接着在yy_modelWithJSON方法中又会调用yy_modelWithDictionary方法将NSDictionary对象转换为Model类的对象,该方法先将Model类的信息进行提取【包含所有属性的信息、所有属性的key和keyPath的mapper字典等等】生成YYModelMeta类的对象
- 接着创建一个元字典来存放属性的各种信息比如属性名和属性类型、修饰符,【为了后面验证类型时就能直接通过元字典验证】,在创建元字典的方法中首先会创建缓存来存放解析后的类(YYModelMeta),后面每次解析先访问缓存,如果没找到在创建新的元数据存到缓存中,接着调用initWithClass方法经过
黑白名单的过滤
,自定义属性映射
,指定容器类属性内元素类型
等一系列操作才能得到我们最终存放的元数据的元字典****_allPropertyMetas
****(key是属性名,value是属性信息) - 建立属性信息和JSON数据之间的映射关系,通过对自定义映射规则的解析,将模型类的各个属性与其在JSON数据中的对应键进行匹配
- 最后获取JSON数据的字典和解析后的类YYModelMeta,通过yy_modelSetWithDictionary方法将JSON数据通过setter方法赋值给对应的属性
原文地址:https://blog.csdn.net/m0_73974920/article/details/142396236
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!