Ivar 详解

作者: 秀才不才 | 来源:发表于2015-12-03 16:40 被阅读4662次

    1.Ivar

    1.1Ivar 的类型

    typedef objc_ivar * Ivar;

      struct objc_ivar {
         char *ivar_name;
         char *ivar_type;
         int ivar_offset;
      #ifdef __LP64__
         int space;
      #endif
      } 
    

    Ivarobjc_ivar的指针,包含变量名,变量类型等成员。

    1.2为类添加 Ivar

    运行时规定,只能在objc_allocateClassPairobjc_registerClassPair两个函数之间为类添加变量

    如下所示:

      //额外空间     未知,通常设置为 0
      Class clazz = objc_allocateClassPair(父类class,类名,额外空间);
      //以NSString*为例
      //变量size sizeof(NSString)
      //对齐     指针类型的为log2(sizeof(NSString*))
      //类型     @encode(NSString*)
      BOOL flag = class_addIvar(clazz,变量名,变量size,对齐,类型);
      objc_registerClassPair(clazz);
    
    1.3 Ivar的相关操作
      //获取Ivar的名称
      const char *ivar_getName(Ivar v);
      //获取Ivar的类型编码,
      const char *ivar_getTypeEncoding(Ivar v)
      //通过变量名称获取类中的实例成员变量
      Ivar class_getInstanceVariable(Class cls, const char *name)
      //通过变量名称获取类中的类成员变量
      Ivar class_getClassVariable(Class cls, const char *name)
      //获取指定类的Ivar列表及Ivar个数
      Ivar *class_copyIvarList(Class cls, unsigned int *outCount)
      //获取实例对象中Ivar的值
      id object_getIvar(id obj, Ivar ivar) 
      //设置实例对象中Ivar的值
      void object_setIvar(id obj, Ivar ivar, id value)
    
    1.4 Ivar的使用
      //在运行时创建继承自NSObject的People类
      Class People = objc_allocateClassPair([NSObject class], "People", 0);
      //添加_name成员变量
      BOOL flag1 = class_addIvar(People, "_name", sizeof(NSString*), log2(sizeof(NSString*)), @encode(NSString*));
      if (flag1) {
          NSLog(@"NSString*类型  _name变量添加成功");
      }
      //添加_age成员变量
      BOOL flag2 = class_addIvar(People, "_age", sizeof(int), sizeof(int), @encode(int));
      if (flag2) {
          NSLog(@"int类型 _age变量添加成功");
      }
      //完成People类的创建
      objc_registerClassPair(People);
      unsigned int varCount;
      //拷贝People类中的成员变量列表
      Ivar * varList = class_copyIvarList(People, &varCount);
      for (int i = 0; i<varCount; i++) {
          NSLog(@"%s",ivar_getName(varList[i]));
      }
      //释放varList
      free(varList);
      //创建People对象p1
      id p1 = [[People alloc]init];
      //从类中获取成员变量Ivar
      Ivar nameIvar = class_getInstanceVariable(People, "_name");
      Ivar ageIvar = class_getInstanceVariable(People, "_age");
      //为p1的成员变量赋值
      object_setIvar(p1, nameIvar, @"张三");
      object_setIvar(p1, ageIvar, @33);
      //获取p1成员变量的值
      NSLog(@"%@",object_getIvar(p1, nameIvar));
      NSLog(@"%@",object_getIvar(p1, ageIvar));
    

    2. Property

    2.1 objc_property_t 与 objc_property_attribute_t类型

    typedef struct objc_property *objc_property_t;

      //特性
      typedef struct {
          const char *name;           //特性名称
          const char *value;          //特性的值
      } objc_property_attribute_t;
    

    特性相关编码
    属性的特性字符串 以 T@encode(type) 开头, 以 V实例变量名称 结尾,中间以特性编码填充,通过property_getAttributes即可查看

    特性编码 具体含义
    R readonly
    C copy
    & retain
    N nonatomic
    G(name) getter=(name)
    S(name) setter=(name)
    D @dynamic
    W weak
    P 用于垃圾回收机制

    2.2 为类添加Property
      BOOL class_addProperty(Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount)
    
    2.3 Property的相关操作
      //替换类中的属性
      void class_replaceProperty(Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount)
      //获取类中的属性
      objc_property_t class_getProperty(Class cls, const char *name)
      //拷贝类中的属性列表
      objc_property_t *class_copyPropertyList(Class cls, unsigned int *outCount)
      //获取属性名称
      const char *property_getName(objc_property_t property)
      //获取属性的特性
      const char *property_getAttributes(objc_property_t property) 
      //拷贝属性的特性列表
      objc_property_attribute_t *property_copyAttributeList(objc_property_t property, unsigned int *outCount)
      //拷贝属性的特性的值
      char *property_copyAttributeValue(objc_property_t property, const char *attributeName)
    
    2.4 Property的使用
      Class People = objc_allocateClassPair([NSObject class], "People", 0);
      objc_registerClassPair(People);
      //T@
      objc_property_attribute_t attribute1;
      attribute1.name = "T";
      attribute1.value=@encode(NSString*);
      //Noatomic
      objc_property_attribute_t attribute2 = {"N",""};//value无意义时通常设置为空
      //Copy
      objc_property_attribute_t attribute3 = {"C",""};
      //V_属性名
      objc_property_attribute_t attribute4 = {"V","_name"};
      //特性数组
      objc_property_attribute_t attributes[] ={attribute1,attribute2,attribute3,attribute4};
      //向People类中添加名为name的属性,属性的4个特性包含在attributes中
      class_addProperty(People, "name", attributes, 4);
      //获取类中的属性列表
      unsigned int propertyCount;
      objc_property_t * properties = class_copyPropertyList(People, &propertyCount);
      for (int i = 0; i<propertyCount; i++) {
          NSLog(@"属性的名称为 : %s",property_getName(properties[i]));
          NSLog(@"属性的特性字符串为: %s",property_getAttributes(properties[i]));
      }
      //释放属性列表数组
      free(properties);
    

    转载自:这里

    相关文章

      网友评论

      • AirZilong:给你点赞,虽然你少写了很多关于Method的方法,依然给你点赞
        秀才不才:@AirZilong 谢啦,我这也是网上搜集来的,有待提高啊:smiley:
      • Jorris:这好像是老的运行时
      • 7a946bf5d2ca:Ivar和objc_property_t有什么区别?
        秀才不才:@大博哥 变量跟属性的区别

      本文标题:Ivar 详解

      本文链接:https://www.haomeiwen.com/subject/wuhshttx.html