runtime之变量和属性

转载文章

1.Ivar

1.1 Ivar的类型

typedef objc_ivar * Ivar;

struct objc_ivar {
    char *ivar_name;          //ivar名称                          
    char *ivar_type;        //ivar类型
    int ivar_offset;        //ivar偏移量
    #ifdef __LP64__
        int space;
    #endif
}//ObjC2.0 已过时

Ivar是objc_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

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;
特效编码 具体含义
R readonly
C copy
& retain
N nonatomic
G(name) getter=(name)
S(name) setter = (name)
D @dynamic
W weak
P 用于垃圾回收

特性相关编码
属性的特性字符串 以 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)

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

你可能感兴趣的:(runtime之变量和属性)