【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方法赋值给对应的属性
相关推荐
开开心心就好2 小时前
解决打印机共享难题的实用工具
人工智能·vscode·游戏·macos·音视频·语音识别·媒体
Digitally2 小时前
如何顺畅将传音 Infinix 数据传输到 Mac?
macos
SameX2 小时前
独立开发了一款健康记录 App,聊聊几个让我纠结很久的设计决策
ios
报错小能手3 小时前
Swift UI 框架 实战 简易计数器、待办清单 、随机壁纸图库、个人笔记
ui·ios
游戏开发爱好者85 小时前
深入理解iOSTime Profiler:提升iOS应用性能的关键工具
android·ios·小程序·https·uni-app·iphone·webview
for_ever_love__21 小时前
UI学习:多界面传值的正向传值(属性传值)和反向传值(代理传值)
学习·ui·ios·objective-c
开心就好20251 天前
全面介绍iOS开发工具:Xcode、AppCode、CocoaPods、Fastlane和Git
后端·ios
懋学的前端攻城狮1 天前
数据持久化与缓存策略:在离线与在线间架起桥梁
ios·swift
~央千澈~1 天前
以cocos3.8.8开发的游戏为例商业实战项目举例cocos打包ios苹果安装包ipa完整详细教程-优雅草卓伊凡
ios
SameX1 天前
iOS 足迹 App 的成就系统,我推倒重做了一次——踩了3个坑之后
ios