YYModel 源码解读之YYClassInfo.h

Posted 马在路上

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了YYModel 源码解读之YYClassInfo.h相关的知识,希望对你有一定的参考价值。

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 }

上边的方法 主要是找出所有的和属性相关的信息,并转换为自定义的类型

以上是关于YYModel 源码解读之YYClassInfo.h的主要内容,如果未能解决你的问题,请参考以下文章

YYModel 源码解读之YYClassInfo.h

YYModel学习总结YYClassInfo

YYModel 源码解读之YYModel.h

YYModel 源码解读之NSObject+YYModel.h

YYModel 源码解读之NSObject+YYModel.h

YYModel 源码解读之NSObject+YYModel.h