有许多人不知道runtime 黑魔法到底是干啥用的,到底有什么卵用,今天我们就来讲讲runtime - 关联对象objc_setAssociatedObject 的使用。
惯例美女大图一张,拿去撸!不客气!
YP59~RBX2LOZ$MOJ8$WDSX8.jpg
使用关联,我们可以不用修改类的定义而为其对象增加存储空间。这在我们无法访问到类的源码的时候或者是考虑到二进制兼容性的时候是非常有用。
有四个参数
1.被关联的对象 即源对象
2.要关联的对象的键值,一般设置成静态的,用于获取关联对象的值(就是给你要添加的东西起个名字而已)
3.关联的对象
4.关联时采用的协议,有assign,retain,copy等协议 点击进去选取枚举
objc_setAssociatedObject(self, &associatedButtonkey, blcok, OBJC_ASSOCIATION_COPY_NONATOMIC);
//通过 objc_getAssociatedObject获取关联对象
objc_getAssociatedObject(self, &associatedButtonkey);
//使用函数objc_removeAssociatedObjects可以断开所有关联。通常情况下不建议使用这个函数,因为他会断开所有关联。只有在需要把对象恢复到“原始状态”的时候才会使用这个函数。
断开关联是使用objc_setAssociatedObject函数,传入nil值即可。
objc_setAssociatedObject(self, &associatedButtonkey, nil, OBJC_ASSOCIATION_COPY_NONATOMIC);
下面我们就用这个鬼东西给UIButton绑定一个Block
先创建一个UIButton的category
然后声明一个block属性 确切的说不是属性,其实是生成了两个方法getter 和 setter
static const char associatedButtonkey;
typedef void (^btnBlock)(id sender);
@property (nonatomic, copy) btnBlock blcok;
声明一个方法
+ (instancetype)WB_fatoryButtonWithFrame:(CGRect)frame
WithTitle:(NSString *)title
WithTitleColor:(UInt32)titleHexColor
Withfont:(CGFloat)font
Withimage:(id)image
WithselImage:(id)selImage
toSuperView:(UIView *)superView
WithClick:(btnBlock)block;
+ (instancetype)WB_fatoryButtonWithFrame:(CGRect)frame
WithTitle:(NSString *)title
WithTitleColor:(UInt32)titleHexColor
Withfont:(CGFloat)font
Withimage:(id)image
WithselImage:(id)selImage
toSuperView:(UIView *)superView
WithClick:(btnBlock)block{
UIButton *btn = [[UIButton alloc] initWithFrame:frame];
[superView addSubview:btn];
btn.titleLabel.font = [UIFont systemFontOfSize:font];
[btn setTitleColor:[UIColor colorWithRGBHex:titleHexColor alpha:1] forState:UIControlStateNormal];
if (!kIsEmptyString(title)) {
[btn setTitle:title forState:UIControlStateNormal];
}
UIImage *normalImage = nil;
if ([image isKindOfClass:[NSString class]]) {
normalImage = kImage(image);
} else if ([image isKindOfClass:[UIImage class]]) {
normalImage = image;
}
UIImage *selectedImage = nil;
if ([selImage isKindOfClass:[NSString class]]) {
selectedImage = kImage(selImage);
} else if ([selImage isKindOfClass:[UIImage class]]) {
selectedImage = selImage;
}
if (normalImage) {
[btn setImage:normalImage forState:UIControlStateNormal];
}
if (selectedImage) {
[btn setImage:selectedImage forState:UIControlStateSelected];
}
if (block)
{
//这里调用setter
btn.blcok = block;
}
return btn;
}
- (void)btnAction:(id)sender{
// 这里调用getter
self.blcok(sender);
}
// setter
- (void)setBlcok:(btnBlock)blcok{
// 给UIButton 关联一个block
objc_setAssociatedObject(self, &associatedButtonkey, blcok, OBJC_ASSOCIATION_COPY_NONATOMIC);
[self removeTarget:self
action:@selector(btnAction:)
forControlEvents:UIControlEventTouchUpInside];
if (blcok) {
[self addTarget:self
action:@selector(btnAction:)
forControlEvents:UIControlEventTouchUpInside];
}
}
//getter
- (btnBlock)blcok{
// 之前说过的给起个名字,通过那个名字获取添加的 block
return objc_getAssociatedObject(self, &associatedButtonkey);
}
最后提醒小伙伴们不要忘记了import