【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 方法来制定容器内的元素类型

Objective-C 复制代码
#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方法赋值给对应的属性
相关推荐
2501_915918412 小时前
HTTP抓包工具推荐,Fiddler使用教程、代理设置与调试技巧详解(含HTTPS配置与实战案例)
http·ios·小程序·https·fiddler·uni-app·webview
mjhcsp3 小时前
C++ 贪心算法(Greedy Algorithm)详解:从思想到实战
c++·ios·贪心算法
Digitally4 小时前
如何在iPhone 17/16/15上显示电池百分比
ios·cocoa·iphone
2501_9159214311 小时前
iOS 虚拟位置设置实战,多工具协同打造精准调试与场景模拟环境
android·ios·小程序·https·uni-app·iphone·webview
QuantumLeap丶11 小时前
《Flutter全栈开发实战指南:从零到高级》- 11 -状态管理Provider
android·flutter·ios
私人珍藏库11 小时前
Clip Studio Paint EX v2.0.6 For MacOS – 官方版本+逆向补丁下载,M4芯片Mac实机测试好用
macos
绝世唐门三哥11 小时前
MacOS-Terminal直接command解压缩文件文件夹
macos·命令行·压缩
2501_9160088911 小时前
App 上架需要什么?从开发者账号到开心上架(Appuploader)免 Mac 上传的完整流程指南
macos·ios·小程序·uni-app·objective-c·cocoa·iphone
crazy_yun11 小时前
laya3如何打包mac包
macos·layabox3
麦麦大数据14 小时前
MacOS 安装Python 3.13【同时保留旧版本】
开发语言·python·macos·python安装