zoukankan      html  css  js  c++  java
  • 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 (nonatomic, assign, readonly) ptrdiff_t offset;       ///< Ivar's offset
     8 @property (nonatomic, strong, readonly) NSString *typeEncoding; ///< Ivar's type encoding
     9 @property (nonatomic, assign, readonly) YYEncodingType type;    ///< Ivar's type
    10 
    11 /**
    12  Creates and returns an ivar info object.
    13  
    14  @param ivar ivar opaque struct
    15  @return A new object, or nil if an error occurs.
    16  */
    17 - (instancetype)initWithIvar:(Ivar)ivar;
    18 @end

    上边代码通过创建Ivar(成员变量)的 抽象类, 返回我们需要的关于Ivar 的信息,

    通过一个初始化方法创建,接下来我们看看该方法的具体实现

     1 - (instancetype)initWithIvar:(Ivar)ivar {
     2     // 初始化判空 如果为空 就返回nil
     3     if (!ivar) return nil;
     4     self = [super init];
     5     _ivar = ivar;
     6     
     7     // 获取成员变量的名称
     8     const char *name = ivar_getName(ivar);
     9     if (name) {
    10         
    11         // 把c的字符串转化成oc的字符串
    12         _name = [NSString stringWithUTF8String:name];
    13     }
    14     
    15     _offset = ivar_getOffset(ivar);
    16     
    17     // 获取类型编码
    18     const char *typeEncoding = ivar_getTypeEncoding(ivar);
    19     if (typeEncoding) {
    20         
    21         // 转为oc的字符穿
    22         _typeEncoding = [NSString stringWithUTF8String:typeEncoding];
    23         
    24         // 转成枚举值
    25         _type = YYEncodingGetType(typeEncoding);
    26    
    27     }
    28     return self;
    29 }
    ivar_getName
    ivar_getTypeEncoding
    ivar_getOffset

    这三个方法都是运行时方法,分别用来获取 名称 , 类型编码 , 偏移量 尤其要之处的是
    ivar_getOffset方法: 官方文档中的描述是这样的
    1 Returns the offset of an instance variable.
    2 
    3 Declaration
    4 ptrdiff_t ivar_getOffset( Ivar ivar)
    5 Discussion
    6 For instance variables of type id or other object types, call object_getIvar and object_setIvar instead of using this offset to access the instance variable data directly.

    ivar_getOffset函数,对于类型id或其它对象类型的实例变量,可以调用object_getIvar和object_setIvar来直接访问成员变量,而不使用偏移量。

    接下来我们看看Method(方法)的 抽象类

     1 /**
     2  Method information.
     3  */
     4 @interface YYClassMethodInfo : NSObject
     5 @property (nonatomic, assign, readonly) Method method;                  ///< method opaque struct
     6 @property (nonatomic, strong, readonly) NSString *name;                 ///< method name
     7 @property (nonatomic, assign, readonly) SEL sel;                        ///< method's selector
     8 @property (nonatomic, assign, readonly) IMP imp;                        ///< method's implementation
     9 @property (nonatomic, strong, readonly) NSString *typeEncoding;         ///< method's parameter and return types
    10 @property (nonatomic, strong, readonly) NSString *returnTypeEncoding;   ///< return value's type
    11 @property (nullable, nonatomic, strong, readonly) NSArray<NSString *> *argumentTypeEncodings; ///< array of arguments' type
    12 
    13 /**
    14  Creates and returns a method info object.
    15  
    16  @param method method opaque struct
    17  @return A new object, or nil if an error occurs.
    18  */
    19 - (instancetype)initWithMethod:(Method)method;
    20 @end

    这这段代码中 比较陌生的是Method 和 IMP

    Method 是一个结构体: 

    struct objc_method
    {
      SEL method_name;
      char * method_types;
      IMP method_imp;
    };

    1.方法名:方法名为此方法的方法签名,相同函数名和参数的方法名是一样的
    2.方法类型: 描述方法的参数类型
    3. 方法真实实现代码块的地址指针,可像C 一样直接调用
     1 - (instancetype)initWithMethod:(Method)method {
     2     if (!method) return nil;
     3     self = [super init];
     4     _method = method;
     5     
     6     // Method获取方法的名称
     7     _sel = method_getName(method);
     8     
     9     // 方法的实现地址
    10     _imp = method_getImplementation(method);
    11     
    12     // SEL 获取方法名
    13     const char *name = sel_getName(_sel);
    14     if (name) {
    15         _name = [NSString stringWithUTF8String:name];
    16     }
    17     
    18     // 获取类型
    19     const char *typeEncoding = method_getTypeEncoding(method);
    20     if (typeEncoding) {
    21         _typeEncoding = [NSString stringWithUTF8String:typeEncoding];
    22     }
    23     
    24     // 获取返回值类型
    25     char *returnType = method_copyReturnType(method);
    26     if (returnType) {
    27         _returnTypeEncoding = [NSString stringWithUTF8String:returnType];
    28         
    29         // 但凡 通过copy retain alloc 系统方法得到的内存,必须使用relea() 或 free() 进行释放
    30         free(returnType);
    31     }
    32     
    33     // 获取参数列表
    34     unsigned int argumentCount = method_getNumberOfArguments(method);
    35     if (argumentCount > 0) {
    36         
    37         NSMutableArray *argumentTypes = [NSMutableArray new];
    38         
    39         for (unsigned int i = 0; i < argumentCount; i++) {
    40             
    41             // 获取参数中的某一个参数
    42             char *argumentType = method_copyArgumentType(method, i);
    43             
    44             NSString *type = argumentType ? [NSString stringWithUTF8String:argumentType] : nil;
    45             [argumentTypes addObject:type ? type : @""];
    46             if (argumentType) free(argumentType);
    47         }
    48         _argumentTypeEncodings = argumentTypes;
    49     }
    50     return self;
    51 }

    上边的代码使用了运行时中 关于Method 的一些方法,再次不做介绍,但值得注意的是

     但凡 通过copy retain alloc 系统方法得到的内存,必须使用relea() 或 free() 进行释放

     1 /**
     2  Property information.
     3  */
     4 @interface YYClassPropertyInfo : NSObject
     5 @property (nonatomic, assign, readonly) objc_property_t property; ///< property's opaque struct
     6 @property (nonatomic, strong, readonly) NSString *name;           ///< property's name
     7 @property (nonatomic, assign, readonly) YYEncodingType type;      ///< property's type
     8 @property (nonatomic, strong, readonly) NSString *typeEncoding;   ///< property's encoding value
     9 @property (nonatomic, strong, readonly) NSString *ivarName;       ///< property's ivar name
    10 @property (nullable, nonatomic, assign, readonly) Class cls;      ///< may be nil
    11 @property (nonatomic, assign, readonly) SEL getter;               ///< getter (nonnull)
    12 @property (nonatomic, assign, readonly) SEL setter;               ///< setter (nonnull)
    13 
    14 /**
    15  Creates and returns a property info object.
    16  
    17  @param property property opaque struct
    18  @return A new object, or nil if an error occurs.
    19  */
    20 - (instancetype)initWithProperty:(objc_property_t)property;

    上边的类是对属性的抽象类,让我们通过下边的代码 了解下属性编码的知识

     1     objc_property_t property = class_getProperty([YYWeiboStatus class], "user");
     2     
     3     unsigned int num;
     4     objc_property_attribute_t *attr = property_copyAttributeList(property, &num);
     5     for (unsigned int i = 0; i < num; i++) {
     6         
     7         objc_property_attribute_t att = attr[i];
     8         fprintf(stdout, "name = %s , value = %s 
    ",att.name , att.value);
     9     }
    10     
    11     const char *chars = property_getAttributes(property);
    12     fprintf(stdout, "%s 
    ",chars);

    打印的输出结果为

    1 name = T , value = @"YYWeiboUser" 
    2 name = & , value =  
    3 name = N , value =  
    4 name = V , value = _user 
    5 T@"YYWeiboUser",&,N,V_user 

    可以看出,比较重要的是属性的编码都是以T开头 标示属性的类型  以V开头 标示属性的变量名

    
    
      1 - (instancetype)initWithProperty:(objc_property_t)property {
      2     if (!property) return nil;
      3     self = [self init];
      4     
      5     _property = property;
      6     
      7     // 1. 获取属性名称
      8     const char *name = property_getName(property);
      9     if (name) {
     10         _name = [NSString stringWithUTF8String:name];
     11     }
     12     
     13     // 2.获取每一个属性的编码字符串
     14     YYEncodingType type = 0;
     15     unsigned int attrCount;
     16     objc_property_attribute_t *attrs = property_copyAttributeList(property, &attrCount);
     17     
     18     // 3. 编译每一个属性的 objc_property_attribute_t
     19     for (unsigned int i = 0; i < attrCount; i++) {
     20         
     21         // 3.1 根据objc_property_attribute_t 中的name 做一些事
     22         switch (attrs[i].name[0]) {
     23                 
     24                 // T 代码属性的类型编码
     25             case 'T': { // Type encoding
     26                 if (attrs[i].value) {
     27                     _typeEncoding = [NSString stringWithUTF8String:attrs[i].value];
     28                     type = YYEncodingGetType(attrs[i].value);
     29                     
     30                     // 计算属性的实体类型 比如:@"User"
     31                     if ((type & YYEncodingTypeMask) == YYEncodingTypeObject) {
     32                         
     33                         size_t len = strlen(attrs[i].value); // len = 7
     34                         if (len > 3) {
     35                             char name[len - 2]; // 新建一个长度 = len - 2 的name字符数组 长度为5
     36                             name[len - 3] = '';   // 设置最后一个字符为
     37                             memcpy(name, attrs[i].value + 2, len - 3); // copy USer 到name 中,
     38                            
     39                             // 获取name 的真实实体类型
     40                             _cls = objc_getClass(name);
     41                         }
     42                     }
     43                 }
     44             } break;
     45             case 'V': { // Instance variable
     46                 if (attrs[i].value) {
     47                     _ivarName = [NSString stringWithUTF8String:attrs[i].value];
     48                 }
     49             } break;
     50             case 'R': {
     51                 type |= YYEncodingTypePropertyReadonly;
     52             } break;
     53             case 'C': {
     54                 type |= YYEncodingTypePropertyCopy;
     55             } break;
     56             case '&': {
     57                 type |= YYEncodingTypePropertyRetain;
     58             } break;
     59             case 'N': {
     60                 type |= YYEncodingTypePropertyNonatomic;
     61             } break;
     62             case 'D': {
     63                 type |= YYEncodingTypePropertyDynamic;
     64             } break;
     65             case 'W': {
     66                 type |= YYEncodingTypePropertyWeak;
     67             } break;
     68             case 'G': { // getter 方法
     69                 type |= YYEncodingTypePropertyCustomGetter;
     70                 if (attrs[i].value) {
     71                     _getter = NSSelectorFromString([NSString stringWithUTF8String:attrs[i].value]);
     72                 }
     73             } break;
     74             case 'S': { // setter 方法
     75                 type |= YYEncodingTypePropertyCustomSetter;
     76                 if (attrs[i].value) {
     77                     _setter = NSSelectorFromString([NSString stringWithUTF8String:attrs[i].value]);
     78                 }
     79             } // break; commented for code coverage in next line
     80             default: break;
     81         }
     82     }
     83     if (attrs) {
     84         free(attrs);
     85         attrs = NULL;
     86     }
     87     
     88     _type = type;
     89     
     90     // 获取setter 和 getter 方法
     91     if (_name.length) {
     92         if (!_getter) {
     93             _getter = NSSelectorFromString(_name);
     94         }
     95         if (!_setter) {
     96             _setter = NSSelectorFromString([NSString stringWithFormat:@"set%@%@:", [_name substringToIndex:1].uppercaseString, [_name substringFromIndex:1]]);
     97         }
     98     }
     99     return self;
    100 }
    
    

    最后让我来看看打印结果

    1  objc_property_t property = class_getProperty([YYWeiboStatus class], "user");
    2     
    3     YYClassPropertyInfo *propertyInfo = [[YYClassPropertyInfo alloc] initWithProperty:property];
    4 
    5     NSLog(@"%@",propertyInfo.typeEncoding);
    1 2016-05-23 16:00:12.134 ModelBenchmark[12626:245778] @"YYWeiboUser"
    1 typedef struct example {
    2     int* aPint;
    3     double  aDouble;
    4     char *aString;
    5     int  anInt;
    6     BOOL isMan;
    7     struct example *next;
    8 } Example;
    1 @property (nonatomic, assign) Example example;
    1 2016-05-23 16:04:59.493 ModelBenchmark[12684:250528] {example=^id*iB^{example}}
    1 objc_property_t property = class_getProperty([YYWeiboStatus class], "statusID");
    2     
    3     YYClassPropertyInfo *propertyInfo = [[YYClassPropertyInfo alloc] initWithProperty:property];
    4 
    5     NSLog(@"%@",propertyInfo.typeEncoding);
    1 2016-05-23 16:06:39.747 ModelBenchmark[12696:252148] Q
    到此 关于 Ivar Method Property  的抽象类已经介绍完毕,在后面的使用中 直接使用这些抽象类来进行编码的

  • 相关阅读:
    METHODS OF AND APPARATUS FOR USING TEXTURES IN GRAPHICS PROCESSING SYSTEMS
    Display controller
    Graphics processing architecture employing a unified shader
    Graphics-Processing Architecture Based on Approximate Rendering
    Architectures for concurrent graphics processing operations
    Procedural graphics architectures and techniques
    DYNAMIC CONTEXT SWITCHING BETWEEN ARCHITECTURALLY DISTINCT GRAPHICS PROCESSORS
    Thermal zone monitoring in an electronic device
    System and method for dynamically adjusting to CPU performance changes
    Framework for Graphics Animation and Compositing Operations
  • 原文地址:https://www.cnblogs.com/machao/p/5520367.html
Copyright © 2011-2022 走看看