Ivar 详解

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
  }

Ivar是objc_ivar的指针,包含变量名,变量类型等成员。
1.2为类添加 Ivar
运行时规定,只能在objc_allocateClassPair与objc_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);

本文转自简书中 ‘Ivar 详解’ 作者:秀才不才 地址:http://www.jianshu.com/p/ead476cdb828

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值