主要函数
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);
id objc_getAssociatedObject(id object, const void *key);
void objc_removeAssociatedObjects(id object);
相关说明
objc_setAssociatedObject 相当于 setValue:forKey 进行关联value对象
objc_getAssociatedObject 用来读取对象
objc_AssociationPolicy 属性 是设定该value在object内的属性,即 assgin, (retain,nonatomic)...等
objc_removeAssociatedObjects 函数来移除一个关联对象,或者使用objc_setAssociatedObject函数将key指定的关联对象设置为nil。
相关参数
key:要保证全局唯一,key与关联的对象是一一对应关系。必须全局唯一。通常用@selector(methodName)作为key。
value:要关联的对象。
policy:关联策略。有五种关联策略。
OBJC_ASSOCIATION_ASSIGN 等价于 @property(assign)。
OBJC_ASSOCIATION_RETAIN_NONATOMIC等价于 @property(strong, nonatomic)。
OBJC_ASSOCIATION_COPY_NONATOMIC等价于@property(copy, nonatomic)。
OBJC_ASSOCIATION_RETAIN等价于@property(strong,atomic)。
OBJC_ASSOCIATION_COPY等价于@property(copy, atomic)。
应用场景
关联对象相当于实例变量,在类别(也有人管叫分类)里面,不能创建实例变量, 关联对象就可以解决这种问题。
使用举例
typedef void(^btnBlock)(id sender);
@interface UIButton (Block)
- (void)handleWithBlock:(btnBlock)block;
@end
#import "UIButton+Block.h"
#import <objc/runtime.h>
static NSString *btnKey = @"safsaf";
@implementation UIButton (Block)
- (void)handleWithBlock:(btnBlock)block{
if (block) {
objc_setAssociatedObject(self, &btnKey, block, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
[self addTarget:self action:@selector(btnAction:) forControlEvents:UIControlEventTouchUpInside];
}
- (void)btnAction:(id)send{
btnBlock block = objc_getAssociatedObject(self, &btnKey);
if (block) {
block(send);
}
}
@end
注
是第二个参数 const void *key 类型通常都是通常都是会采用静态变量来作为关键字 可以自己创建 也可以使用"@selector(btnAction:) "。
扩展
可对第二个参数进一步优化,用_cmd 代替了 &btnKey 或者 @selector(methodName).
_cmd在Objective-C的方法中表示当前方法的selector,正如同self表示当前方法调用的对象实例。
强调
_cmd的作用域只在当前方法里,直指当前方法名@selector。例如:
- (void)btnAction:(id)send{
btnBlock block = objc_getAssociatedObject(self, _cmd);
//这里_cmd相当于@selector(btnAction:)
if (block) {
block(send);
}
}
WX20190108-115018.png
至此,设置关联对象关键key,一共有三种写法:
(1)静态变量&btnKey
(2)@selector(methodName)
(3)_cmd
网友评论