在之前的一篇文章中已經介紹過, 可以通過 runtime 機制給已有的類"添加"對象屬性和非對象屬性)[詳情]. 那么接下來, 再給系統(tǒng)的
UIButton
添加一個 block 屬性(畢竟在 iOS 中, block 是一種 id 類型), 當點擊 button 時, 直接觸發(fā) block 塊中的代碼, 這樣就可以避免每次使用UIButton
時都要調用系統(tǒng)的addTarget: action: forControlEvents:
方法.
- 首先給需要使用的 block 類型定義一個別名:
typedef void(^MHButtonActionCallBack)(UIButton *button);
這樣當需要使用這種 bolck 類型的時候, 就不需要把注意力放在 block 的具體內容上了, 即: 不需要考慮 block 的傳參和返回值類型了.
- 利用iOS runtime 應用之給 NSString 添加對象屬性和非對象屬性中介紹的原理給
UIButton
"添加"一個MHButtonActionCallBack
類型的屬性(誠然, 這種"添加"并不是嚴格意義上的添加, 只不過是添加了一對getter
和setter
方法而已):
- (void)setMHCallBack:(MHButtonActionCallBack)callBack {
objc_setAssociatedObject(self, &_callBack, callBack, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (MHButtonActionCallBack)getMHCallBack {
return (MHButtonActionCallBack)objc_getAssociatedObject(self, &_callBack);
}
這樣就可以放心大膽的使用UIButton
的setMHCallBack:
和getMHCallBack:
方法進行賦值和取值操作了.
- 為了便于調用, 還要把上一步"添加"的"屬性", 封裝到
UIButton
內部, 只暴露出下面的方法:
- (void)addMHClickAction:(MHButtonActionCallBack)callBack;
至此, 當需要給UIButton
添加點擊事件的時候, 就可以直接調用這個方法就可以了.
附上完整代碼:
UIButton+MHExtra.h
#import <UIKit/UIKit.h>
typedef void(^MHButtonActionCallBack)(UIButton *button);
@interface UIButton (MHExtra)
/**
* @brief replace the method 'addTarget:forControlEvents:'
*/
- (void)addMHCallBackAction:(MHButtonActionCallBack)callBack forControlEvents:(UIControlEvents)controlEvents;
/**
* @brief replace the method 'addTarget:forControlEvents:UIControlEventTouchUpInside'
* the property 'alpha' being 0.5 while 'UIControlEventTouchUpInside'
*/
- (void)addMHClickAction:(MHButtonActionCallBack)callBack;
@end
UIButton+MHExtra.m
#import "UIButton+MHExtra.h"
#import <objc/runtime.h>
/**
* @brief add action callback to uibutton
*/
@interface UIButton (MHAddCallBackBlock)
- (void)setMHCallBack:(MHButtonActionCallBack)callBack;
- (MHButtonActionCallBack)getMHCallBack;
@end
@implementation UIButton (MHAddCallBackBlock)
static MHButtonActionCallBack _callBack;
- (void)setMHCallBack:(MHButtonActionCallBack)callBack {
objc_setAssociatedObject(self, &_callBack, callBack, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (MHButtonActionCallBack)getMHCallBack {
return (MHButtonActionCallBack)objc_getAssociatedObject(self, &_callBack);
}
@end;
@implementation UIButton (MHExtra)
/**
* @brief replace the method 'addTarget:forControlEvents:UIControlEventTouchUpInside'
* the property 'alpha' being 0.5 while 'UIControlEventTouchUpInside'
*/
- (void)addMHClickAction:(MHButtonActionCallBack)callBack {
[self addMHCallBackAction:callBack forControlEvents:(UIControlEventTouchUpInside)];
[self addTarget:self action:@selector(mhTouchDownAction:) forControlEvents:(UIControlEventTouchDown)];
[self addTarget:self action:@selector(mhTouchUpAction:) forControlEvents:(UIControlEventTouchUpInside | UIControlEventTouchUpOutside | UIControlEventTouchCancel | UIControlEventTouchDragOutside)];
}
/**
* @brief replace the method 'addTarget:forControlEvents:'
*/
- (void)addMHCallBackAction:(MHButtonActionCallBack)callBack forControlEvents:(UIControlEvents)controlEvents{
[self setMHCallBack:callBack];
[self addTarget:self action:@selector(mhButtonAction:) forControlEvents:controlEvents];
}
- (void)mhButtonAction:(UIButton *)btn {
self.getMHCallBack(btn);
}
- (void)mhTouchDownAction:(UIButton *)btn {
btn.enabled = NO;
btn.alpha = 0.5f;
}
- (void)mhTouchUpAction:(UIButton *)btn {
btn.enabled = YES;
btn.alpha = 1.0f;
}
@end
從現(xiàn)在開始, 當需要給UIBuootn
添加點擊事件的時候, 就不需要先調用addTarget: action: forControlEvents:
, 然后在實現(xiàn)其中的action
方法了, 直接:
[btn addMHClickAction:^(UIButton *button) {
NSLog(@"clicked button");
}];
就 O 了~
至此, 給UIButton
添加點擊事件的 block 就完成了!
如果各位有什么好的思路或者對我的代碼有什么優(yōu)化, 歡迎積極留言哦~