在我们平常的开发当中经常会碰到测试会去快速点击按钮。如果按钮没有做时间拦截处理,那么就会出现按钮的方法会执行多次,这样是不行的,我在这里也是参照网上的有一些资料,写了个demo,有需要的朋友可以直接拿走。分类都知道是不能直接添加属性的,因为添加属性他不会自动生成get和set放法,运行就会崩溃,这就需要我们用runtime来做点事情了。
runtime的作用什么,在开发中能帮助我们做些什么事情?
- 1.最常见的就是字典转模型:MJExtention, YYModel等底层均使用runtime操作,使用class_getProperty来获取模型当中的所有属性,最后与返回的数据进行比对,有相同的key就使用KVC进行赋值操作,也可访问私有属性进行取值和赋值操作
- 2.可以在运行的时候交换系统的方法,让他执行我们自己的方法方便进行扩展操作
- 3.为分类添加属性并关联对象
这里我就使用runtime动态的为分类添加属性以便进行扩展操作
- 由于按钮是继承UIControl的,我这里就直接为UIControl添加分类即可
#import <UIKit/UIKit.h>
@interface UIControl (BtnQuickLimit)
//添加两个属性
// 间隔多少秒才能响应事件
@property(nonatomic, assign) NSTimeInterval acceptEventInterval;
//是否能执行方法
@property(nonatomic, assign) BOOL ignoreEvent;
@end
#import "UIControl+BtnQuickLimit.h"
#import <objc/runtime.h>
static const char * UIControl_acceptEventInterval = "UIControl_acceptEventInterval";
static const char * UIControl_ignoreEvent = "UIControl_ignoreEvent";
@implementation UIControl (BtnQuickLimit)
-(void)setAcceptEventInterval:(double)acceptEventInterval {
//关联属性对象
objc_setAssociatedObject(self, UIControl_acceptEventInterval,@(acceptEventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(NSTimeInterval)acceptEventInterval{
return [objc_getAssociatedObject(self, UIControl_acceptEventInterval) doubleValue];
}
-(void)setIgnoreEvent:(BOOL)ignoreEvent {
//关联属性对象
objc_setAssociatedObject(self, UIControl_ignoreEvent, @(ignoreEvent), OBJC_ASSOCIATION_ASSIGN);
}
-(BOOL)ignoreEvent{
return [objc_getAssociatedObject(self, UIControl_ignoreEvent) boolValue];
}
//所有类即将加入内存的时候都会走load方法,所以我们在这个里面交换方法
+(void)load{
Method a = class_getInstanceMethod(self, @selector(sendAction:to:forEvent:));
Method b = class_getInstanceMethod(self, @selector(swizzing_sendAction:to:forEvent:));
method_exchangeImplementations(a, b);
}
-(void)swizzing_sendAction:(SEL)action to:(id)tagert forEvent:(UIEvent*)event{
if (self.ignoreEvent) {
NSLog(@"你点击的太快了");
return;
}
if (self.acceptEventInterval>0) {
self.ignoreEvent = YES;
//之前是写的有点问题,现在改了一下,把下面这段话给注释掉,就会只响应一次点击,前提是:acceptEventInterval 的数据必须大于0,否则会一直走调用的方法
// [self performSelector:@selector(setIgnoreWithNo) withObject:nil afterDelay:self.acceptEventInterval];
//如果想要按钮延迟一定的时间去响应事件,就可以打开上面的方法即可
[self performSelector:@selector(setIgnoreWithNo) withObject:nil afterDelay:self.acceptEventInterval];
}
//当前按钮调用该方法
[self swizzing_sendAction:action to:tagert forEvent:event];
}
-(void)setIgnoreWithNo{
self.ignoreEvent = NO;
}
@end
最后在UIViewController中创建按钮的时候直接使用
-(void)creatSubView {
self.view.backgroundColor = [UIColor whiteColor];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(200, 200, 100, 50);
btn.backgroundColor = [UIColor redColor];
btn.acceptEventInterval = 1.0;
[btn setTitle:@"快速点击" forState:UIControlStateNormal];
[self.view addSubview:btn];
[btn addTarget:self action:@selector(quiklyClick) forControlEvents:UIControlEventTouchUpInside];
}
-(void)quiklyClick{
NSLog(@"快速点击。。。。。。。。");
}
文章会持续更新,有什么不好的地方还请路过的大神多多指正。相互学习