一般給按鈕添加事件是這樣的組合:
// 把點擊后要調用的方法名傳到@selector中
self.btn addTarget:self action:@selector(btnClick) forControlEvents:UIControlEventTouchUpInside];
// 找別的地方寫上方法的實現(xiàn)
- (void)btnClick {
}
這樣寫代碼多不說,工程大的話還得到處找方法。
所以我寫了一個分類燕少,可以用block
來代替@selector()
,防止代碼分散蒿囤。
使用起來是這樣的:
// button
[self.btn addTarget:self action:[self selectorBlock:^(id arg) {
NSLog(@"clicked %@", arg);
}] forControlEvents:UIControlEventTouchUpInside];
下面講一下分類NSObject+BlockSEL.h
中的實現(xiàn)原理
- (SEL)selectorBlock:(void (^)(id))block {
NSString *selName = [NSString stringWithFormat:@"selector_%p:", block];
SEL sel = NSSelectorFromString(selName);
class_addMethod([self class], sel, (IMP)selectorImp, "v@:@");
objc_setAssociatedObject(self, sel, block, OBJC_ASSOCIATION_COPY_NONATOMIC);
return sel;
}
static void selectorImp(id self, SEL _cmd, id arg) {
void (^block)(id arg) = objc_getAssociatedObject(self, _cmd);
if (block) block(arg);
}
用block
的內存地址
創(chuàng)建一個唯一方法客们,并將方法實現(xiàn)綁定到selectorImp
函數(shù)。將block
用關聯(lián)對象保存下來材诽,在調用時執(zhí)行block
底挫。
需要注意一下,當block中使用self
時會產(chǎn)生循環(huán)引用脸侥,需要用__weak來修飾防止self無法釋放建邓。
__weak typeof(self) weakSelf = self;
[self.btn addTarget:self action:[self selectorBlock:^(id arg) {
weakSelf.view.backgroundColor = [UIColor whiteColor];
}] forControlEvents:UIControlEventTouchUpInside];