runtime总结2:成员变量与属性

1.基础数据类型

Ivar
是表示实例变量的类型,其实际是一个指向objc_ivar
结构体的指针,其定义如下:

typedef struct objc_ivar *Ivar;

struct objc_ivar {

char *ivar_name OBJC2_UNAVAILABLE; // 变量名
char *ivar_type OBJC2_UNAVAILABLE; // 变量类型
int ivar_offset OBJC2_UNAVAILABLE; // 基地址偏移字节

#ifdef __LP64__
int space OBJC2_UNAVAILABLE;
#endif
}

objc_property_t
objc_property_t是表示Objective-C声明的属性的类型,其实际是指向objc_property结构体的指针,其定义如下:

typedefstruct objc_property *objc_property_t;

objc_property_attribute_t

objc_property_attribute_t定义了属性的特性(attribute),它是一个结构体,定义如下:

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

2.关联对象(Associated Object)

关联对象可以用在分类添加成员变量,我们可以把关联对象想象成一个Objective-C对象(如字典),这个对象通过给定的key连接到类的一个实例上。不过由于使用的是C接口,所以key是一个void指针(const void *)。我们还需要指定一个内存管理策略

OBJC_ASSOCIATION_ASSIGN
OBJC_ASSOCIATION_RETAIN_NONATOMIC
OBJC_ASSOCIATION_COPY_NONATOMIC
OBJC_ASSOCIATION_RETAIN
OBJC_ASSOCIATION_COPY

当宿主对象被释放时,会根据指定的内存管理策略来处理关联对象。如果指定的策略是assign,则宿主释放时,关联对象不会被释放;而如果指定的是retain或者是copy,则宿主释放时,关联对象会被释放。我们甚至可以选择是否是自retain/copy。当我们需要在多个线程中处理访问关联对象的多线程代码时,这就非常有用了。

static char myKey;
objc_setAssociatedObject(self, &myKey, anObject, OBJC_ASSOCIATION_RETAIN);
在这种情况下,self对象将获取一个新的关联的对象anObject,且内存管理策略是自动retain关联对象,当self对象释放时,会自动release关联对象。另外,如果我们使用同一个key来关联另外一个对象时,也会自动释放之前关联的对象,这种情况下,先前的关联对象会被妥善地处理掉,并且新的对象会使用它的内存。
id anObject = objc_getAssociatedObject(self, &myKey);
我们可以使用objc_removeAssociatedObjects函数来移除一个关联对象,或者使用objc_setAssociatedObject函数将key指定的关联对象设置为nil。
关联对象操作函数包括以下:

// 设置关联对象
void objc_setAssociatedObject ( id object, const void *key, id value, objc_AssociationPolicy policy );

// 获取关联对象
id objc_getAssociatedObject ( id object, const void *key );

// 移除关联对象
void objc_removeAssociatedObjects ( id object );

你可能感兴趣的:(runtime总结2:成员变量与属性)