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 }

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

时间: 2024-10-11 03:26:59

YYModel 源码解读(二)之YYClassInfo.h (1)的相关文章

YYModel 源码解读(二)之NSObject+YYModel.h (1)

本篇文章主要介绍 _YYModelPropertyMeta 前边的内容 首先先解释一下前边的辅助函数和枚举变量,在写一个功能的时候,这些辅助的东西可能不是一开始就能想出来的,应该是在后续的编码过程中 逐步添加的. #define force_inline __inline__ __attribute__((always_inline)) 这行代码用到了C语言的内联函数 内联函数: 是用inline修饰的函数,内联函数在代码层次看和普通的函数结构一样,却不具备函数的性质,内联函数不是在调用时发生控

(转)go语言nsq源码解读二 nsqlookupd、nsqd与nsqadmin

转自:http://www.baiyuxiong.com/?p=886 ----------------------------------------------------------------------- 上一篇go语言nsq源码解读-基本介绍  介绍了最基本的nsq环境搭建及使用.在最后使用时,我们用到了几个命令:nsqlookupd.nsqd.nsqadmin.curl及 nsq_to_file,并看到用curl命令写入的几个”hello world”被nsq_to_file命令保

YYModel 源码解读(二)之YYClassInfo.h (3)

前边3篇介绍了YYClassinfo 文件的组成单元,算是功能的分割,按照业务的设计思想来说,方向应该是相反的 由此引申出我们在设计api的思想其实和项目管理是很类似的----- 一些题外话 1.目的 回到代码,首先应该明确写这个类的目的是什么? 按照正常逻辑,我们需要一个类来获取我们所需要的所有和此类相关的信息 包括(类名,父类,成员变量,方法,属性...) 2.技术调研 调研我们所需要的结果是否能够通过技术手段实现 3.目标分隔,也就是任务分解 需要把整体目标分解成小目标,在本代码中则分割成

YYModel 源码解读之YYModel.h (一)

#if __has_include(<YYModel/YYModel.h>) FOUNDATION_EXPORT double YYModelVersionNumber; FOUNDATION_EXPORT const unsigned char YYModelVersionString[]; #import <YYModel/NSObject+YYModel.h> #import <YYModel/YYClassInfo.h> #else #import "

YYModel 源码解读 总结

在使用swfit写代码的过程中,使用了下oc写的字典转模型,发现有些属性转不成功,就萌生了阅读源码的想法. 其实一直都知道Runtime机制,但并没有系统的学习,可能是因为平时的使用比较少,无意间在github上看到了YYModel ,粗略的看了下源码,发现有大量的c方面的知识,就产生了很大的兴趣,因为c总是性能的代名词吗?于是就有了这几篇文章,其实主要的目的还是对平时所学知识的一个总结. 毕竟,人类的记忆总是容易忘记的. 不知道作者在写这个框架时的思想是怎么样一个过程?但字里行间都流露出对代码

YYModel 源码解读(二)之YYClassInfo.h (2)

1 /** 2 Instance variable information. 3 */ 4 @interface YYClassIvarInfo : NSObject 5 @property (nonatomic, assign, readonly) Ivar ivar; ///< ivar opaque struct 6 @property (nonatomic, strong, readonly) NSString *name; ///< Ivar's name 7 @property (

YYModel 源码解读(二)之NSObject+YYModel.h (4)

接下来我们继续向下看 typedef struct { void *modelMeta; ///< _YYModelMeta void *model; ///< id (self) void *dictionary; ///< NSDictionary (json) } ModelSetContext; 这是一个c的结构体,在c中 void * 相当于 oc 中的 id 类型 那么 为什么使用c的结构体呢,最主要的使用场景就是我们需要同时使用多个参数的情况下,可以使用c的结构体 /**

YYModel 源码解读(二)之NSObject+YYModel.h (5)

好了,之前的博文中详细的解释了一些辅助的类和辅助的函数,接下来就是使用它们来实现酷炫功能的时候,正所谓磨刀不误砍柴工啊 我们先把总的功能罗列出来 1. json转字典              + (NSDictionary *)_yy_dictionaryWithJSON:(id)json 2. json转模型              + (instancetype)yy_modelWithJSON:(id)json 3. 字典转模型              + (instancetype

YYModel 源码解读(二)之NSObject+YYModel.h (3)

本篇主要介绍的是 在真正转之前的几个辅助函数 /** Get number from property. @discussion Caller should hold strong reference to the parameters before this function returns. @param model Should not be nil. @param meta Should not be nil, meta.isCNumber should be YES, meta.get