分类中不可以添加成员变量
- 分类中可以声明属性,分类中声明属性只会生成方法的声明,但不会生成成员变量和方法的实现。
- 分类中不可以声明成员变量,在分类中声明成员变量会报
instance variables may not be placed in categories
- 通过 Category 的底层结构可以看出分类是不支持添加成员变量的,因为 category 的结构体中没有用来存放成员变量的变量
struct category_t{
const char *name;
classref_t cls;
struct method_list_t *instanceMethods;
struct method_list_t *classMethods;
struct protocol_list_t *protocols;
struct property_list_t *instanceProperties;
struct property_list_t *classProperties;
method_list_t *methodsforMeta(bool isMeta) {
if(isMeta) return classMethods;
else return instanceMethods;
}
property_list_t *propertiesForMeta(bool isMeta, struct header_info *hi);
}
分类中添加关联属性
- 添加关联对象:
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
- 获得关联对象:
id objc_getAssociatesObject(id object, const void *key)
- 移除所有关联对象:
void objc_removeAssociatedObjects(id object)
key 的写法
-
key
必须保证是唯一的地址值 -
static void *nameKey = &nameKey
:
objc_setAssociatedObject(self, nameKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_getAssociatedObject(obj,nameKey)
-
static char name
:
objc_setAssociatedObject(self, &name, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_getAssociatedObject(obj,&name)
@selector(name)
objc_setAssociatedObject(self, @selector(name), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_getAssociatedObject(obj,_cmd)
@"name"
objc_setAssociatedObject(self, @"name", value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_getAssociatedObject(obj,@"name")
关联对象原理
- 实现关联对象技术的核心对象有
1、AssociationsManager
class AssociationsManager {
static AssociationsHashMap *_map;
}
2、 AssociationsHashMap
class AssociationsHasMap : public unordered_map<disguised_ptr_t,ObjectAssociationMap>
3、 ObjectAssociateMap
class ObjectAssociationMap : public std::map<void *, ObjcAssociation>
4、 ObjcAssociation
class ObjcAssociation {
uintptr_t _policy;
id _value;
}
image.png
-
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
中的四个参数与关联对象核心对象的关系:
1、object
对应AssociationsHashMap
中的key disguised_ptr_t
,key disguised_ptr_t
是object
的地址经过位运算得到的
2、key
对应AssociationsMap
中的void *
3、value
对应ObjectAssociation
中的_value
4、policy
对应ObjectAssociation
中的_policy
- 关联对象并不是存储在被关联对象本身内存中,而是存储在全局统一的一个
AssociationsMananger
中,AssociationsManager
中管理着一个AssociationsHashMap
,AssociationsHashMap
中以传入的object
为key
,ObjectAssociationMap
对象作为value
,ObjectAssociationMap
中以出入的 地址指针key
作为key
,ObjectAssociation
对象作为value
,ObjectAssociation
中存放着关联策略和关联值。 - 当关联属性的值设置为
nil
的时候,相当于移除关联对象 - 当对象被销毁时,会移除该对象对应的
ObjectAssociationMap