有許多人不知道runtime 黑魔法到底是干啥用的,到底有什么卵用,今天我們就來講講runtime - 關(guān)聯(lián)對象objc_setAssociatedObject 的使用嫌变。
慣例美女大圖一張令境,拿去擼!不客氣!
使用關(guān)聯(lián)馏臭,我們可以不用修改類的定義而為其對象增加存儲(chǔ)空間。這在我們無法訪問到類的源碼的時(shí)候或者是考慮到二進(jìn)制兼容性的時(shí)候是非常有用讼稚。
有四個(gè)參數(shù)
1.被關(guān)聯(lián)的對象 即源對象
2.要關(guān)聯(lián)的對象的鍵值括儒,一般設(shè)置成靜態(tài)的,用于獲取關(guān)聯(lián)對象的值(就是給你要添加的東西起個(gè)名字而已)
3.關(guān)聯(lián)的對象
4.關(guān)聯(lián)時(shí)采用的協(xié)議锐想,有assign帮寻,retain,copy等協(xié)議 點(diǎn)擊進(jìn)去選取枚舉
objc_setAssociatedObject(self, &associatedButtonkey, blcok, OBJC_ASSOCIATION_COPY_NONATOMIC);
//通過 objc_getAssociatedObject獲取關(guān)聯(lián)對象
objc_getAssociatedObject(self, &associatedButtonkey);
//使用函數(shù)objc_removeAssociatedObjects可以斷開所有關(guān)聯(lián)赠摇。通常情況下不建議使用這個(gè)函數(shù)固逗,因?yàn)樗麜?huì)斷開所有關(guān)聯(lián)。只有在需要把對象恢復(fù)到“原始狀態(tài)”的時(shí)候才會(huì)使用這個(gè)函數(shù)藕帜。
斷開關(guān)聯(lián)是使用objc_setAssociatedObject函數(shù)抒蚜,傳入nil值即可。
objc_setAssociatedObject(self, &associatedButtonkey, nil, OBJC_ASSOCIATION_COPY_NONATOMIC);
下面我們就用這個(gè)鬼東西給UIButton綁定一個(gè)Block
先創(chuàng)建一個(gè)UIButton的category
然后聲明一個(gè)block屬性 確切的說不是屬性耘戚,其實(shí)是生成了兩個(gè)方法getter 和 setter
static const char associatedButtonkey;
typedef void (^btnBlock)(id sender);
@property (nonatomic, copy) btnBlock blcok;
聲明一個(gè)方法
+ (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)
{
//這里調(diào)用setter
btn.blcok = block;
}
return btn;
}
- (void)btnAction:(id)sender{
// 這里調(diào)用getter
self.blcok(sender);
}
// setter
- (void)setBlcok:(btnBlock)blcok{
// 給UIButton 關(guān)聯(lián)一個(gè)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{
// 之前說過的給起個(gè)名字嗡髓,通過那個(gè)名字獲取添加的 block
return objc_getAssociatedObject(self, &associatedButtonkey);
}
最后提醒小伙伴們不要忘記了import