什么是这个问题
我们的按钮是点击一次响应一次, 即使频繁的点击也不会出问题, 可是某些场景下还偏偏就是会出问题.
通常是如何解决
我们通常会在按钮点击的时候设置这个按钮不可点击. 等待0.xS的延时后,在设置回来; 或者在操作结束的时候设置可以点击.
- (IBAction)clickBtn1:(UIbutton *)sender{ sender.enabled=NO; doSomething sender.enabled=YES;}
1
2
3
4
5
6
如果涉及到按钮不同状态不同样式的时候, 用enabled不见得够用.还得额外加个变量来记录状态.
- (IBAction)clickBtn1:(UIbutton *)sender{if(doingSomeThing)return; doingSomeThing =YES; doSomething doingSomeThing =NO;}
1
2
3
4
5
6
7
8
笔者举的例子是直接在响应事件的周期内直接禁止点击的. 如果想做1秒内禁止重复点击的话,则得用performSelector:withObject:afterDelay:
漂亮的解决是怎样的
有了重复的代码段就是有了一个共性, 就可以抽象出来.
我们可以给按钮添加一个属性重复点击间隔, 通过设置这个属性来控制再次接受点击事件的时间间隔.
@interfaceUIControl(XY)@property(nonatomic,assign)NSTimeIntervaluxy_acceptEventInterval;// 可以用这个给重复点击加间隔@endstaticconstchar*UIControl_acceptEventInterval ="UIControl_acceptEventInterval";- (NSTimeInterval)uxy_acceptEventInterval{return[objc_getAssociatedObject(self, UIControl_acceptEventInterval) doubleValue];}- (void)setUxy_acceptEventInterval:(NSTimeInterval)uxy_acceptEventInterval{ objc_setAssociatedObject(self, UIControl_acceptEventInterval, @(uxy_acceptEventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
在app启动的时候,我们hook 所有的按钮的 event
@implementationUIControl(XY)+ (void)load{ Method a = class_getInstanceMethod(self,@selector(sendAction:to:forEvent:)); Method b = class_getInstanceMethod(self,@selector(__uxy_sendAction:to:forEvent:)); method_exchangeImplementations(a, b);}@end
1
2
3
4
5
6
7
8
9
10
在我们的点击事件里呢,对点击事件做下过滤
-(void)__uxy_sendAction:(SEL)actionto:(id)target forEvent:(UIEvent*)event{if(NSDate.date.timeIntervalSince1970-self.uxy_acceptedEventTime0) {self.uxy_acceptedEventTime=NSDate.date.timeIntervalSince1970; }[self__uxy_sendAction:actionto:target forEvent:event];
}
1
2
3
4
5
6
7
8
9
10
11
实际使用起来就是这个样子
UIButton*tempBtn = [UIButtonbuttonWithType:UIButtonTypeCustom]; [tempBtn addTarget:selfaction:@selector(clickWithInterval:) forControlEvents:UIControlEventTouchUpInside]; tempBtn.uxy_acceptEventInterval=0.5;
1
2
3
文章至此就结束了.虽然不推荐大范围用runtime, 但是小范围内使用还是可以解决不少小问题的.