自学内容网 自学内容网

【iOS】——YYModel源码总结

性能优化及优点

YYModel主要用于将JSON数据转换为模型对象,以及将模型对象转换为字典的库。相比于其他的数据转换库例如JSONModel,它更加的轻量级并且性能更高,因为它在很多地方做了优化:

  • 通过CFDictionaryCreateMutable方法将数据存入缓存,需要使用的时候直接拿出,就不用重复解析类,该方法是C语言,相比于JSONModel使用关联对象进行缓存省去了OC的消息发送,性能更高。
  • 并且通过getter和setter方法用JSON数据给模型的属性进行赋值而不是像JSONModel通过kvc赋值从而提高性能。因为前者可以利用编译时优化、静态类型检查以及直接访问底层实例变量。而KVC需要在运行时进行更多的动态查找和类型检查。
  • 在内存管理中大量使用__unsafe_unretained而不是__strong和__weak因为__unsafe_unretained仅涉及简单的指针赋值操作,完全避免了引用计数的增减开销及相关的内存管理和同步操作,因此性能更高。但使用时必须非常小心以避免产生悬垂指针问题。因为__unsafe_unretained指针指向的对象被释放后指针不会置nil还是指向原来的地址,但是该地址的内容已经被释放,访问的话存在安全性问题。(野指针通常指向从未有效分配的内存,而悬垂指针曾有效但对象已被销毁或内存已被释放。)
  • 在处理键值映射和类型转换时,会用到如YYClassIvarInfoYYClassMethodInfo这样的C结构体来存储有关ivar和方法的信息,然后通过纯C函数来操作这些结构体,避免了频繁的ObjC方法调用。
  • 减少遍历的循环次数,在 JSONModel 转换前,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)!