关联是指把两个对象相互关联起来,使得其中的一个对象作为另外一个对象的一部分。就是说一个对象可以保持对另一个对象的引用,并获取那个对象。有了这些,就能实现属性功能了。
这是iOS中运行时的特性,所以首先要导入 #import
typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {
OBJC_ASSOCIATION_ASSIGN = 0, //表示弱引用关联,通常是基本数据类型,如int、float
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, //表示强(strong)引用关联对象
OBJC_ASSOCIATION_COPY_NONATOMIC = 3, //表示关联对象copy
OBJC_ASSOCIATION_RETAIN = 01401, //表示强(strong)引用关联对象,但不是线程安全的
OBJC_ASSOCIATION_COPY = 01403 //表示关联对象copy,但不是线程安全的
};
/**
设置关联,需要使用下面的API关联起来
object:与谁关联,通常是传self
key:唯一键,在获取值时通过该键获取,通常是使用static const void *来声明
value:关联所设置的值
policy:内存管理策略,比如使用copy
**/
OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
__OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_1);
/**
获取所关联的值,需要通过key来获取
object:与谁关联,通常是传self,在设置关联时所指定的与哪个对象关联的那个对象
key:唯一键,在设置关联时所指定的键
**/
OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key)
__OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_1);
//这个我们几乎不会用到,因为他会断开所有关联。只有在需要把对象恢复到“原始状态”的时候才会使用这个函数。
OBJC_EXPORT void objc_removeAssociatedObjects(id object)
__OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_1);
我们来看一个例子
static char overviewKey;
NSArray *array = [[NSArray alloc] initWithObjects:@"测试1",@"测试2",@"测试3", nil];
NSString *overview = @"浮点数";
//设置关联
objc_setAssociatedObject(array, &overviewKey, overview, OBJC_ASSOCIATION_RETAIN);
//取出关联值
NSString *associatedObject = (NSString *)objc_getAssociatedObject(array, &overviewKey);
NSLog(@"%@",associatedObject);
//断开关联
objc_setAssociatedObject(array, &overviewKey, nil, OBJC_ASSOCIATION_ASSIGN);
用起来还是比较简单的,那下面我们就可以给其他的控件添加操作了,我们这里给UIControl添加一个block
typedef void (^DCTouchUpBlock)(id sender);
@interface UIControl (DCControl)
@property (nonatomic, copy) DCTouchUpBlock dc_touchUpBlock;
@end
#import
static const void *kDCTouchUpBlockKey = "kDCTouchUpBlockKey";
@implementation UIControl (DCControl)
- (void)setDc_touchUpBlock:(DCTouchUpBlock)dc_touchUpBlock{
objc_setAssociatedObject(self,
kDCTouchUpBlockKey,
dc_touchUpBlock,
OBJC_ASSOCIATION_COPY);
[self removeTarget:self
action:@selector(dcOnTouchUp:)
forControlEvents:UIControlEventTouchUpInside];
if (dc_touchUpBlock) {
[self addTarget:self
action:@selector(dcOnTouchUp:)
forControlEvents:UIControlEventTouchUpInside];
}
}
- (DCTouchUpBlock)dc_touchUpBlock {
return objc_getAssociatedObject(self, kDCTouchUpBlockKey);
}
- (void)dcOnTouchUp:(UIButton *)sender {
DCTouchUpBlock touchUp = self.dc_touchUpBlock;
if (touchUp) {
touchUp(sender);
}
}
@end
来看一下用法
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(20, 40, 280, 50)];
button.backgroundColor = [UIColor blueColor];
[button setTitle:@"点我啊" forState:UIControlStateNormal];
[self.view addSubview:button];
button.dc_touchUpBlock = ^(UIButton *sender){
NSLog(@"%@",sender.titleLabel.text);
};
运行结果是这样滴
是不是简单多了~