實(shí)現(xiàn)
category無(wú)法添加成員變量,category編譯之后,會(huì)生成struct _category_t類(lèi)型的結(jié)構(gòu)體,包含instance_methods(對(duì)象方法列表),class_methods(類(lèi)方法列表),protocols(協(xié)議列表),properties(屬性列表),沒(méi)有類(lèi)似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;
};
不過(guò)我們可以通過(guò)設(shè)置關(guān)聯(lián)對(duì)象的方式添加屬性,當(dāng)我們#import <objc/runtime.h>之后,可以通過(guò)如下方法
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為如下結(jié)構(gòu),分別對(duì)應(yīng)不同的屬性聲明(由于關(guān)聯(lián)對(duì)象是通過(guò)全局Map維護(hù),所以沒(méi)有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. */
};
實(shí)現(xiàn)方式為:
// .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));
}
原理
通過(guò)查看objc_setAssociatedObject源碼得知,有一個(gè)AssociationsManager管理關(guān)聯(lián)對(duì)象,其結(jié)構(gòu)部署為:
AssociationsManager
AssociationsHashMap
ObjectAssociationMap
ObjcAssociation

objc_setAssociatedObject(id object, const void * key, id value, objc_AssociationPolicy policy);
AssociationsManager維護(hù)著一張AssociationsHashMap結(jié)構(gòu)的HashMap,以objc_setAssociatedObject中第一個(gè)參數(shù)[object]作為key,找出對(duì)應(yīng)的ObjectAssociationMap,ObjectAssociationMap也是一個(gè)Map,以我們傳遞的第二個(gè)參數(shù)[key]作為key,找出對(duì)應(yīng)的ObjcAssociation(當(dāng)我們這個(gè)key傳遞為nil,將刪除ObjcAssociation鍵值對(duì)),這個(gè)ObjcAssociation里面維護(hù)著兩個(gè)參數(shù),就是我們傳遞的后兩個(gè)參數(shù):[value]、[policy]。取值的時(shí)候就通過(guò)兩個(gè)key,找出對(duì)應(yīng)的值
總結(jié)
category添加成員變量的實(shí)現(xiàn),實(shí)際上是通過(guò)一個(gè)雙重Map來(lái)存儲(chǔ)將要存儲(chǔ)的屬性值,第一層Map維護(hù)各個(gè)category分類(lèi)的添加成員變量的實(shí)現(xiàn),第二層Map,維護(hù)這個(gè)category中的成員變量賦值操作。