概况
YYClassInfo作为YYModel的核心类,是YYModel解析Json转模型必不可少的部分,其实它主要是利用runTime来获取class内部信息,从而为json转model提供了便利工具。学习YYClassInfo类有助于理解YYModel的工作原理,也有利于加强runTime的基本功。Let’s get started.
YYClassInfo类预览
YYClassInfo类.h文件和.m文件其实都是可以分为5个部分,(读者可以看下源代码对比下)分别为:
- YYEncodingType
- YYClassIvarInfo
- YYClassMethodInfo
- YYClassPropertyInfo
- YYClassInfo
每个部分负责一个具体的职责,根据5部分顺序,接下来进行逐一的具体分析。
YYEncodingType模块
//YYClassInfo.h
/**
Type encoding's type.
*/
typedef NS_OPTIONS(NSUInteger, YYEncodingType) {
YYEncodingTypeMask = 0xFF, ///< mask of type value
YYEncodingTypeUnknown = 0, ///< unknown
YYEncodingTypeVoid = 1, ///< void
YYEncodingTypeBool = 2, ///< bool
YYEncodingTypeInt8 = 3, ///< char / BOOL
YYEncodingTypeUInt8 = 4, ///< unsigned char
YYEncodingTypeInt16 = 5, ///< short
YYEncodingTypeUInt16 = 6, ///< unsigned short
YYEncodingTypeInt32 = 7, ///< int
YYEncodingTypeUInt32 = 8, ///< unsigned int
YYEncodingTypeInt64 = 9, ///< long long
YYEncodingTypeUInt64 = 10, ///< unsigned long long
YYEncodingTypeFloat = 11, ///< float
YYEncodingTypeDouble = 12, ///< double
YYEncodingTypeLongDouble = 13, ///< long double
YYEncodingTypeObject = 14, ///< id
YYEncodingTypeClass = 15, ///< Class
YYEncodingTypeSEL = 16, ///< SEL
YYEncodingTypeBlock = 17, ///< block
YYEncodingTypePointer = 18, ///< void*
YYEncodingTypeStruct = 19, ///< struct
YYEncodingTypeUnion = 20, ///< union
YYEncodingTypeCString = 21, ///< char*
YYEncodingTypeCArray = 22, ///< char[10] (for example)
YYEncodingTypeQualifierMask = 0xFF00, ///< mask of qualifier
YYEncodingTypeQualifierConst = 1 << 8, ///< const
YYEncodingTypeQualifierIn = 1 << 9, ///< in
YYEncodingTypeQualifierInout = 1 << 10, ///< inout
YYEncodingTypeQualifierOut = 1 << 11, ///< out
YYEncodingTypeQualifierBycopy = 1 << 12, ///< bycopy
YYEncodingTypeQualifierByref = 1 << 13, ///< byref
YYEncodingTypeQualifierOneway = 1 << 14, ///< oneway
YYEncodingTypePropertyMask = 0xFF0000, ///< mask of property
YYEncodingTypePropertyReadonly = 1 << 16, ///< readonly
YYEncodingTypePropertyCopy = 1 << 17, ///< copy
YYEncodingTypePropertyRetain = 1 << 18, ///< retain
YYEncodingTypePropertyNonatomic = 1 << 19, ///< nonatomic
YYEncodingTypePropertyWeak = 1 << 20, ///< weak
YYEncodingTypePropertyCustomGetter = 1 << 21, ///< getter=
YYEncodingTypePropertyCustomSetter = 1 << 22, ///< setter=
YYEncodingTypePropertyDynamic = 1 << 23, ///< @dynamic
};
YYEncodingType YYEncodingGetType(const char *typeEncoding);
解析:以上是YYClassInfo.h文件关于YYEncodingType模块的源代码。首先定义了一个移位枚举类型,该类型的枚举值可以按位取或操作实现多种类型的组合。
其中YYEncodingTypexxx记录了属性的类型,YYEncodingTypeQualifier记录了属性的关键字,YYEncodingTypeProperty记录了属性的修饰。其中YYEncodingTypeMask,YYEncodingTypeQualifierMask,YYEncodingTypePropertyMask,可以实现取值操作,比如其中YYEncodingTypeMask去和枚举值取&操作可以得到低8位的值也就是该枚举的值。也就是说多个枚举值取|操作可以实现多个枚举值的组合,如一个变量可以存储三个枚举值(YYEncodingType,YYEncodingTypeQualifier,YYEncodingTypeProperty)的组合。该变量进行和其中YYEncodingTypeMask取&操作可以取得低8位的值也就是YYEncodingType类型的值通过这种方法就实现了三个状态枚举值得组合与获取具体的哪种枚举值。
YYEncodingType YYEncodingGetType(const char *typeEncoding); 该方法是获取枚举值的方法具体看实现文件
YYEncodingType YYEncodingGetType(const char *typeEncoding) {
char *type = (char *)typeEncoding;
//type为空则返回
if (!type) return YYEncodingTypeUnknown;
size_t len = strlen(type);
//type长度为0,则返回
if (len == 0) return YYEncodingTypeUnknown;
/*** 1.获取YYEncodingTypeQualifier类型值 ***/
//用来存储枚举类型的变量
YYEncodingType qualifier = 0;
//循环结束控制变量
bool prefix = true;
//一下代码用来获取YYEncodingTypeQualifier类型的值存储在qualifier变量里
while (prefix) {
switch (*type) {
case 'r': {
qualifier |= YYEncodingTypeQualifierConst;
type++;
} break;
case 'n': {
qualifier |= YYEncodingTypeQualifierIn;
type++;
} break;
case 'N': {
qualifier |= YYEncodingTypeQualifierInout;
type++;
} break;
case 'o': {
qualifier |= YYEncodingTypeQualifierOut;
type++;
} break;
case 'O': {
qualifier |= YYEncodingTypeQualifierBycopy;
type++;
} break;
case 'R': {
qualifier |= YYEncodingTypeQualifierByref;
type++;
} break;
case 'V': {
qualifier |= YYEncodingTypeQualifierOneway;
type++;
} break;