「这是我参与2022首次更文挑战的第12天,活动详情查看:2022首次更文挑战」。
- 之前我们了解了
Mirror的使用方法,以及通过Mirror解析Json,转换为model。本文主要介绍下Mirror的原理
1. 源码分析
- 在
Mirror.swift文件中找到Mirror,是一个结构体类型
其初始化方法中,先判断传入的对象subject是否遵循CustomReflectable协议,如果符合的话则通过customMirror确定对象的属性。否则通过internalReflecting的方法进行初始化。
internalReflecting查看
主要是:1.通过
_getNormalizedType方法获取传入的subject的类型2.获取对象的属性个数,并遍历属性存储到字典中。3.设置获取父类的 Mirror,继承的关系因此Mirror有个superclassMirror的属性,会返回该类的父类。4.设置Miroor的displayStyle属性。5.设置 subjectType 和 _defaultDescendantRepresentation属性。
- 查看
_getNormalizedType的实现
函数上面使用了一个编译字段
@_silgen_name,这个是 Swift 的一个隐藏符号,作⽤是将某个C/C++函数直接映射为 Swift 函数。也就是我们在调用 _getNormalizedType 函数的时候,最终会调用C++中的swift_reflectionMirror_normalizedType -> Call方法
我们看下
call的实现
主要分为类的调用和非类的调用,对于非类的impl实现通过一个枚举进行判断
ReflectionMirrorImpl,它通过 kind 来判断实例的类型,从而拿到不同类型对应的 impl,调用非类的 call(&impl)。而类是调用 callClass。
ReflectionMirrorImpl的种类主要有以下几种:
- TupleImpl 元组的反射
- StructImpl 结构体的反射
- EnumImpl 枚举的反射
- ClassImpl 类的反射
- MetatypeImpl 元数据的反射
- OpaqueImpl 不透明类型的反射
我们以StructImpl为例子查看
通过
isReflectable 函数来判断是否接受反射,它的实现无非就是拿到 Description,通过 Description 的 isReflectable 函数来判断的。在获取 count 的时候用到了 isReflectable 函数,代码如下:
如果不支持反射,直接返回 0,否则走到下面,调用了一个
getInfo 函数。查看getInfo 函数,它的实现如下:
我们查看
getFieldAt的实现
这里拿到
Description,通过 Description 拿到 Fields,而 Fields 里面包含了属性信息,既然拿到了 Fields,就可以拿到属性相关的信息了。
2.小结
Mirror通过实例对象的meatadata,在其内部创建了一个结构,用于输出metadata中的descriptor,在descriptor中找到name和numFields,通过FieldDescriptor中的fields,来找到对当前属性的描述,然后通过指针移动,获取其他属性