前言
为什么要给UIButton添加block点击事件,要放弃Action-Target的方式?
首先第一个是因为懒,写Action-Target要比写block多写好多代码,还要想一个好一点的方法名,起名什么的最困难啦。
其次是能最快最直观地看到UIButton要做什么事情。
添加方法
为了兼容性和拓展性,所以使用category给UIButton添加了一个属性和两个Block方法。
#import <UIKit/UIKit.h>
typedef void(^ActionBlock)(UIButton* button);
@interface UIButton (block)
@property (nonatomic, copy) ActionBlock actionBlock;
/**
button 添加点击block事件
@param action 点击事件回调
*/
- (void)addAction:(ActionBlock)action;
/**
button 添加点击block事件
@param controlEvents 点击的方式
@param action 点击事件回调
*/
- (void)addControlEvents:(UIControlEvents)controlEvents Action:(ActionBlock)action;
@end
实现代码的逻辑也不复杂:先将传入的block给保存下来,然后给UIButton addTarget一个固定方法,方法中调用block即可。
#import "UIButton+block.h"
#import <objc/runtime.h>
static const char keyActionBlock;
@implementation UIButton (block)
@dynamic actionBlock;
- (void)addAction:(ActionBlock)action
{
[self addControlEvents:UIControlEventTouchUpInside Action:action];
}
- (void)addControlEvents:(UIControlEvents)controlEvents Action:(ActionBlock)action
{
if (!action) {
return;
}
objc_setAssociatedObject(self, &keyActionBlock, action, OBJC_ASSOCIATION_COPY_NONATOMIC);
[self addTarget:self action:@selector(buttonTarget) forControlEvents:controlEvents];
}
- (void)buttonTarget
{
ActionBlock action = (ActionBlock)objc_getAssociatedObject(self, &keyActionBlock);
if (action){
action(self);
}
}
- (void)setActionBlock:(ActionBlock)actionBlock
{
[self addAction:actionBlock];
}
-(ActionBlock)actionBlock
{
return objc_getAssociatedObject(self, &keyActionBlock);
}
@end
使用方式
UIButton *btn = [[UIButton alloc]init];
btn.actionBlock = ^(UIButton *btn) {
NSLog(@"Button Action");
};
[btn addAction:^(UIButton *button) {
NSLog(@"Button Action");
}];
[btn addControlEvents:UIControlEventTouchUpInside Action:^(UIButton *button) {
NSLog(@"Button Action");
}];
缺点
block点击事件的缺点是无法添加多个事件,以及block的通病容易造成循环引用,实际使用上来说基本都会循环引用。