YYModel 源码解读(二)之YYClassInfo.h (1)
1 NS_ASSUME_NONNULL_BEGIN 2 NS_ASSUME_NONNULL_END
为了兼容Swift 中的 ? 和 ! oc 在6.3引入了两个新的类型注释:__nullable和__nonnull , 在字面上很好理解 可能为空, 不为空,
在上面代码中间则表示 默认的所有的属性都不能为空,这样我们在敲码的过程中只需要手写__nullable的类型就可以了
1 /** 2 Type encoding's type. 3 */ 4 typedef NS_OPTIONS(NSUInteger, YYEncodingType) { 5 YYEncodingTypeMask = 0xFF, ///< mask of type value 6 YYEncodingTypeUnknown = 0, ///< unknown 7 YYEncodingTypeVoid = 1, ///< void 8 YYEncodingTypeBool = 2, ///< bool 9 YYEncodingTypeInt8 = 3, ///< char / BOOL 10 YYEncodingTypeUInt8 = 4, ///< unsigned char 11 YYEncodingTypeInt16 = 5, ///< short 12 YYEncodingTypeUInt16 = 6, ///< unsigned short 13 YYEncodingTypeInt32 = 7, ///< int 14 YYEncodingTypeUInt32 = 8, ///< unsigned int 15 YYEncodingTypeInt64 = 9, ///< long long 16 YYEncodingTypeUInt64 = 10, ///< unsigned long long 17 YYEncodingTypeFloat = 11, ///< float 18 YYEncodingTypeDouble = 12, ///< double 19 YYEncodingTypeLongDouble = 13, ///< long double 20 YYEncodingTypeObject = 14, ///< id 21 YYEncodingTypeClass = 15, ///< Class 22 YYEncodingTypeSEL = 16, ///< SEL 23 YYEncodingTypeBlock = 17, ///< block 24 YYEncodingTypePointer = 18, ///< void* 25 YYEncodingTypeStruct = 19, ///< struct 26 YYEncodingTypeUnion = 20, ///< union 27 YYEncodingTypeCString = 21, ///< char* 28 YYEncodingTypeCArray = 22, ///< char[10] (for example) 29 30 YYEncodingTypeQualifierMask = 0xFF00, ///< mask of qualifier 31 YYEncodingTypeQualifierConst = 1 << 8, ///< const 32 YYEncodingTypeQualifierIn = 1 << 9, ///< in 33 YYEncodingTypeQualifierInout = 1 << 10, ///< inout 34 YYEncodingTypeQualifierOut = 1 << 11, ///< out 35 YYEncodingTypeQualifierBycopy = 1 << 12, ///< bycopy 36 YYEncodingTypeQualifierByref = 1 << 13, ///< byref 37 YYEncodingTypeQualifierOneway = 1 << 14, ///< oneway 38 39 YYEncodingTypePropertyMask = 0xFF0000, ///< mask of property 40 YYEncodingTypePropertyReadonly = 1 << 16, ///< readonly 41 YYEncodingTypePropertyCopy = 1 << 17, ///< copy 42 YYEncodingTypePropertyRetain = 1 << 18, ///< retain 43 YYEncodingTypePropertyNonatomic = 1 << 19, ///< nonatomic 44 YYEncodingTypePropertyWeak = 1 << 20, ///< weak 45 YYEncodingTypePropertyCustomGetter = 1 << 21, ///< getter= 46 YYEncodingTypePropertyCustomSetter = 1 << 22, ///< setter= 47 YYEncodingTypePropertyDynamic = 1 << 23, ///< @dynamic 48 };
上边的代码 就涉及到了运行时中的类型解码方面的知识了,在此总结一下
关于Type Encodings 的官方解释 , @encode 是一个编译器指令,返回个内部表示的字符串 , 比如: @encode(int)
→ i ,作用就是可以加快运行时库的消息分发,
需要注意的是:
- 指针的标准编码是加一个前置的
^
,而char *
拥有自己的编码*
。这在概念上是很好理解的,因为 C 的字符串被认为是一个实体,而不是指针。 BOOL
是c
,而不是某些人以为的i
。原因是char
比int
小,且在 80 年代 Objective-C 最开始设计的时候,每一个 bit 位都比今天的要值钱(就像美元一样)。BOOL
更确切地说是signed char
(即使设置了-funsigned-char
参数),以在不同编译器之间保持一致,因为char
可以是signed
或者unsigned
。- 直接传入
NSObject
将产生#
。但是传入[NSObject class]
产生一个名为NSObject
只有一个类字段的结构体。很明显,那就是isa
字段,所有的NSObject
实例都用它来表示自己的类型。
通过打印的数据,看起来更加直观
1 NSLog(@"int : %s", @encode(int)); 2 NSLog(@"float : %s", @encode(float)); 3 NSLog(@"float * : %s", @encode(float*)); 4 NSLog(@"char : %s", @encode(char)); 5 NSLog(@"char * : %s", @encode(char *)); 6 NSLog(@"BOOL : %s", @encode(BOOL)); 7 NSLog(@"void : %s", @encode(void)); 8 NSLog(@"void * : %s", @encode(void *)); 9 10 NSLog(@"NSObject * : %s", @encode(NSObject *)); 11 NSLog(@"NSObject : %s", @encode(NSObject)); 12 NSLog(@"[NSObject] : %s", @encode(typeof([NSObject class]))); 13 NSLog(@"NSError ** : %s", @encode(typeof(NSError **))); 14 15 int intArray[5] = {1, 2, 3, 4, 5}; 16 NSLog(@"int[] : %s", @encode(typeof(intArray))); 17 18 float floatArray[3] = {0.1f, 0.2f, 0.3f}; 19 NSLog(@"float[] : %s", @encode(typeof(floatArray))); 20 21 typedef struct _struct { 22 short a; 23 long long b; 24 unsigned long long c; 25 } Struct; 26 NSLog(@"struct : %s", @encode(typeof(Struct)));
1 2016-05-23 10:42:00.172 ModelBenchmark[1661:72558] int : i 2 2016-05-23 10:42:00.173 ModelBenchmark[1661:72558] float : f 3 2016-05-23 10:42:00.173 ModelBenchmark[1661:72558] float * : ^f 4 2016-05-23 10:42:00.173 ModelBenchmark[1661:72558] char : c 5 2016-05-23 10:42:00.173 ModelBenchmark[1661:72558] char * : * 6 2016-05-23 10:42:00.173 ModelBenchmark[1661:72558] BOOL : B 7 2016-05-23 10:42:00.174 ModelBenchmark[1661:72558] void : v 8 2016-05-23 10:42:00.174 ModelBenchmark[1661:72558] void * : ^v 9 2016-05-23 10:42:00.174 ModelBenchmark[1661:72558] NSObject * : @ 10 2016-05-23 10:42:00.174 ModelBenchmark[1661:72558] NSObject : {NSObject=#} 11 2016-05-23 10:42:00.174 ModelBenchmark[1661:72558] [NSObject] : # 12 2016-05-23 10:42:00.174 ModelBenchmark[1661:72558] NSError ** : ^@ 13 2016-05-23 10:42:00.174 ModelBenchmark[1661:72558] int[] : [5i] 14 2016-05-23 10:42:00.174 ModelBenchmark[1661:72558] float[] : [3f] 15 2016-05-23 10:42:00.174 ModelBenchmark[1661:72558] struct : {_struct=sqQ}
关于 Type Property 和 Functions 的官方解释 ,可以参考官方文档获取编译后的内容
1 YYEncodingType YYEncodingGetType(const char *typeEncoding);
定义一个方法 把typeEncoding 转为自定义的枚举类型,方便管理和使用,
1 YYEncodingType YYEncodingGetType(const char *typeEncoding) { 2 3 // 判断外部传入值 是不是nil,如果为空 ,返回 YYEncodingTypeUnknown 4 // 转换const 限定符 5 char *type = (char *)typeEncoding; 6 if (!type) return YYEncodingTypeUnknown; 7 size_t len = strlen(type); 8 if (len == 0) return YYEncodingTypeUnknown; 9 10 // 找出修饰语 11 YYEncodingType qualifier = 0; 12 bool prefix = true; 13 14 // 可能多个修饰符 15 while (prefix) { 16 17 switch (*type) { 18 case 'r': { 19 qualifier |= YYEncodingTypeQualifierConst; 20 type++; 21 } break; 22 case 'n': { 23 qualifier |= YYEncodingTypeQualifierIn; 24 type++; 25 } break; 26 case 'N': { 27 qualifier |= YYEncodingTypeQualifierInout; 28 type++; 29 } break; 30 case 'o': { 31 qualifier |= YYEncodingTypeQualifierOut; 32 type++; 33 } break; 34 case 'O': { 35 qualifier |= YYEncodingTypeQualifierBycopy; 36 type++; 37 } break; 38 case 'R': { 39 qualifier |= YYEncodingTypeQualifierByref; 40 type++; 41 } break; 42 case 'V': { 43 qualifier |= YYEncodingTypeQualifierOneway; 44 type++; 45 } break; 46 default: { prefix = false; } break; 47 } 48 } 49 50 // 是否还存在后续的字符 51 len = strlen(type); 52 if (len == 0) return YYEncodingTypeUnknown | qualifier; 53 54 // 查找数据类型 55 switch (*type) { 56 case 'v': return YYEncodingTypeVoid | qualifier; 57 case 'B': return YYEncodingTypeBool | qualifier; 58 case 'c': return YYEncodingTypeInt8 | qualifier; 59 case 'C': return YYEncodingTypeUInt8 | qualifier; 60 case 's': return YYEncodingTypeInt16 | qualifier; 61 case 'S': return YYEncodingTypeUInt16 | qualifier; 62 case 'i': return YYEncodingTypeInt32 | qualifier; 63 case 'I': return YYEncodingTypeUInt32 | qualifier; 64 case 'l': return YYEncodingTypeInt32 | qualifier; 65 case 'L': return YYEncodingTypeUInt32 | qualifier; 66 case 'q': return YYEncodingTypeInt64 | qualifier; 67 case 'Q': return YYEncodingTypeUInt64 | qualifier; 68 case 'f': return YYEncodingTypeFloat | qualifier; 69 case 'd': return YYEncodingTypeDouble | qualifier; 70 case 'D': return YYEncodingTypeLongDouble | qualifier; 71 case '#': return YYEncodingTypeClass | qualifier; 72 case ':': return YYEncodingTypeSEL | qualifier; 73 case '*': return YYEncodingTypeCString | qualifier; 74 case '^': return YYEncodingTypePointer | qualifier; 75 case '[': return YYEncodingTypeCArray | qualifier; 76 case '(': return YYEncodingTypeUnion | qualifier; 77 case '{': return YYEncodingTypeStruct | qualifier; 78 case '@': { 79 if (len == 2 && *(type + 1) == '?') 80 return YYEncodingTypeBlock | qualifier; 81 else 82 return YYEncodingTypeObject | qualifier; 83 } 84 default: return YYEncodingTypeUnknown | qualifier; 85 } 86 }
上边的方法 主要是找出所有的和属性相关的信息,并转换为自定义的类型