实现
category无法添加成员变量,category编译之后,会生成struct _category_t类型的结构体,包含instance_methods(对象方法列表),class_methods(类方法列表),protocols(协议列表),properties(属性列表),没有类似ivars这样的成员变量列表
struct _category_t {
const char *name;
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;
};
不过我们可以通过设置关联对象的方式添加属性,当我们#import <objc/runtime.h>之后,可以通过如下方法
OBJC_EXPORT void
objc_setAssociatedObject(id _Nonnull object, const void * _Nonnull key,
id _Nullable value, objc_AssociationPolicy policy);
OBJC_EXPORT id _Nullable
objc_getAssociatedObject(id _Nonnull object, const void * _Nonnull key);
OBJC_EXPORT void
objc_removeAssociatedObjects(id _Nonnull object);
其中objc_AssociationPolicy为如下结构,分别对应不同的属性声明(由于关联对象是通过全局Map维护,所以没有weak声明)
typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {
OBJC_ASSOCIATION_ASSIGN = 0, /**< Specifies a weak reference to the associated object. */
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, /**< Specifies a strong reference to the associated object.
* The association is not made atomically. */
OBJC_ASSOCIATION_COPY_NONATOMIC = 3, /**< Specifies that the associated object is copied.
* The association is not made atomically. */
OBJC_ASSOCIATION_RETAIN = 01401, /**< Specifies a strong reference to the associated object.
* The association is made atomically. */
OBJC_ASSOCIATION_COPY = 01403 /**< Specifies that the associated object is copied.
* The association is made atomically. */
};
实现方式为:
// .h文件
@property (nonatomic, copy) NSString *name;
// .m文件
#import <objc/runtime.h>
- (void)setName:(NSString *)name {
objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString *)name {
return objc_getAssociatedObject(self, @selector(name));
}
原理
通过查看objc_setAssociatedObject源码得知,有一个AssociationsManager管理关联对象,其结构部署为:
AssociationsManager
AssociationsHashMap
ObjectAssociationMap
ObjcAssociation

objc_setAssociatedObject(id object, const void * key, id value, objc_AssociationPolicy policy);
AssociationsManager维护着一张AssociationsHashMap结构的HashMap,以objc_setAssociatedObject中第一个参数[object]作为key,找出对应的ObjectAssociationMap,ObjectAssociationMap也是一个Map,以我们传递的第二个参数[key]作为key,找出对应的ObjcAssociation(当我们这个key传递为nil,将删除ObjcAssociation键值对),这个ObjcAssociation里面维护着两个参数,就是我们传递的后两个参数:[value]、[policy]。取值的时候就通过两个key,找出对应的值
总结
category添加成员变量的实现,实际上是通过一个双重Map来存储将要存储的属性值,第一层Map维护各个category分类的添加成员变量的实现,第二层Map,维护这个category中的成员变量赋值操作。