• 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 }

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

  • 相关阅读:
    【餐厅】 What kind of food would you like to eat tonight?
    深入分析总线设备驱动模型的框架
    总线设备驱动模型
    Qt工程管理
    USB摄像头驱动框架分析
    浅析struct device结构体
    一、mysql下载与安装
    vsCode创建自己的代码模板
    vsCode多选多个元素进行统一修改
    博客园添加目录
  • 原文地址:https://www.cnblogs.com/machao/p/5519605.html
Copyright © 2020-2023  润新知