前言

续前,本文主要谈论类中的变量和属性

1.Ivar

1.1 Ivar的类型

typedef objc_ivar * Ivar;

1
2
3
4
5
6
7
8
	struct objc_ivar {
		char *ivar_name;      	//ivar名称                          
		char *ivar_type;        //ivar类型
		int ivar_offset;		//ivar偏移量
		#ifdef __LP64__
	    	int space;
		#endif
	}//ObjC2.0 已过时

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

1.2 为类添加Ivar

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

如下所示:

1
2
3
4
5
6
7
8
	//额外空间     未知,通常设置为 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的相关操作

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
	//获取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的使用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
	//在运行时创建继承自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;

1
2
3
4
5
	//特性
	typedef struct {
    const char *name;           //特性名称
    const char *value;          //特性的值
	} objc_property_attribute_t;

特性相关编码

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

特性编码具体含义
Rreadonly
Ccopy
&retain
Nnonatomic
G(name)getter=(name)
S(name)setter=(name)
D@dynamic
Wweak
P用于垃圾回收机制

2.2 为类添加Property

1
	BOOL class_addProperty(Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount)

2.3 Property的相关操作

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
	//替换类中的属性
	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的使用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
	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);

参考:

ObjC底层数据类型