文章目录
前言
关联对象的使用一般用于给Category添加成员变量
一般使用
我们知道 分类添加属性只能生成setter
getter
方法的声明
不能自动生成实现 所以我们需要自己实现两个方法
void objc_setAssociatedObject
全称 :
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
参数 :
id object
: 给哪个对象添加属性 这里要给自己添加属性 用self
const void *key
: 根据key
获取关联对象的属性的值 只要是一个指针就好了id value
: 关联的值 也就是setter
方法传入的值给属性去保存objc_AssociationPolicy policy
: 保存策略
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. */
};
对应内存管理方案找就好了 就跟平常属性添加关键字一样
关联对象需要什么样的内存管理方法 就使用哪个方案
用于setter
方法
@property (nonatomic, assign) int weight;
在分类中有这样一个属性
setter方法 :
- (void)setWeight:(int)weight {
objc_setAssociatedObject(self, @"weight", [NSNumber numberWithInt:weight], OBJC_ASSOCIATION_ASSIGN);
}
注意 int
类型的变量需要转成NSNumber
类型使用
不然会报错
[NSNumber numberWithInt:weight]
别的类型一般不需要转
objc_getAssociatedObject
全称 :
id objc_getAssociatedObject(id object, const void *key)
用于getter
方法
- (int)weight {
return [objc_getAssociatedObject(self, @"weight") intValue];
}
这里需要取出来是一个NSNumber
类型 所以后面加了intValue
一般不需要加
在setter
方法中weight
关联了一个NSNumber
对象才需要加
关联对象的实现原理
核心对象
- AssociationsManager
- AssociationsHashMap
- ObjectAssociationMap
- ObjcAssociation
Map可以想象成字典 都是一对一的关系
核心对象之间的关系
class AssociationsManager {
// associative references: object pointer -> PtrPtrHashMap.
// AssociationsManager中只有一个变量AssociationsHashMap
static AssociationsHashMap *_map;
public:
// 构造函数中加锁
AssociationsManager() {
AssociationsManagerLock.lock(); }
// 析构函数中释放锁
~AssociationsManager() {
AssociationsManagerLock.unlock(); }
// 构造函数、析构函数中加锁、释放锁的操作,保证了AssociationsManager是线程安全的
AssociationsHashMap &associations() {
// AssociationsHashMap 的实现可以理解成单例对象
if (_map == NULL)
_map = new AssociationsHashMap();