一、category方法是如何添加的
- 当编译器编译的时候,编译器会将category编译成category_t这样的结构体 如下:
// 分类category底层结构
struct _category_t {
void * isa; // NULL
const char *name; // 类名Person
struct _class_t *cls;
const struct _method_list_t *instance_methods; // 实例方法列表
const struct _method_list_t *class_methods; // 类方法列表
const struct _protocol_list_t *protocols; // 协议列表
const struct _prop_list_t *properties; // 属性列表
};
-
category底层会把等类初始化的时候,会将分类的信息同步到class_rw_t里面,包含:method_list、property_list、protocol_list等,同步的时候会将category里面的信息添加到class的前面(而不是替换掉class里面的方法),而方法调用的时候,而是遍历class_rw_t里面的方法,所以找到分类里面的IMP则返回,这个流程如下:
Category.png
二、category关联属性
-
我们都知道category不能直接添加属性,(原因是底层并没有帮我们生成 对应的 @property = ivar + getter + setter),我们需要自己用truntime的关联方法为分类添加属性 那么关联属性的底层是怎么实现的呢?
objc_setAssociatedObject category A.png - 调用 void _object_set_associative_reference(id object, void *key, id value, uintptr_t policy)
里面包含
1.AssociationsManager
{
static AssociationsHashMap *_map;
}
2.AssociationsHashMap
(
// disguised_ptr_t = DISGUISE(object)
class AssociationsHashMap : public unordered_map<disguised_ptr_t, ObjectAssociationMap >
)
3.ObjectAssociationMap
(
// void * = key
class ObjectAssociationMap : public std::map<void *,ObjcAssociation,>
)
4.ObjcAssociation
{
// d _value =value , uintptr_t policy = uintptr_t _policy;
uintptr_t _policy;
id _value;
}
反推之获取值的时候也是这样获取的
网友评论