用runtime 解决UIButton 重复点击问题
2016-01-07 21:59
423 查看
iOS小技巧–用runtime 解决UIButton 重复点击问题
什么是这个问题
我们的按钮是点击一次响应一次, 即使频繁的点击也不会出问题, 可是某些场景下还偏偏就是会出问题.
通常是如何解决
我们通常会在按钮点击的时候设置这个按钮不可点击. 等待0.xS的延时后,在设置回来; 或者在操作结束的时候设置可以点击.- (IBAction)clickBtn1:(UIbutton *)sender { sender.enabled = NO; doSomething sender.enabled = YES; }
如果涉及到按钮不同状态不同样式的时候, 用enabled不见得够用.还得额外加个变量来记录状态.
- (IBAction)clickBtn1:(UIbutton *)sender { if (doingSomeThing) return; doingSomeThing = YES; doSomething doingSomeThing = NO; }
笔者举的例子是直接在响应事件的周期内直接禁止点击的. 如果想做1秒内禁止重复点击的话,则得用
performSelector:withObject:afterDelay:
漂亮的解决是怎样的
有了重复的代码段就是有了一个共性, 就可以抽象出来.我们可以给按钮添加一个属性
重复点击间隔, 通过设置这个属性来控制再次接受点击事件的时间间隔.
添加一个分类MyBtn
.h文件
#import <UIKit/UIKit.h> @interface UIControl (MyBtn) @property (nonatomic, assign) NSTimeInterval wsj_acceptEventInterval;//添加点击事件的间隔事件 @property (nonatomic, assign) NSTimeInterval wsj_acceptedEventTime;//添加点击事件发生的时间 @end
.m文件
#import "UIControl+MyBtn.h" #import <objc/runtime.h> @implementation UIControl (MyBtn) static const char *UIControl_acceptEventInterval = "UIControl_acceptEventInterval"; static const char *UIControl_acceptEventTime = "UIControl_acceptEventTime"; - (NSTimeInterval)wsj_acceptEventInterval { return [objc_getAssociatedObject(self, UIControl_acceptEventInterval) doubleValue]; } - (void)setWsj_acceptEventInterval:(NSTimeInterval)wsj_acceptEventInterval { objc_setAssociatedObject(self, UIControl_acceptEventInterval, @(wsj_acceptEventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC); } - (NSTimeInterval)wsj_acceptedEventTime { return [objc_getAssociatedObject(self, UIControl_acceptEventTime) doubleValue]; } - (void)setWsj_acceptedEventTime:(NSTimeInterval)wsj_acceptedEventTime { objc_setAssociatedObject(self, UIControl_acceptEventTime, @(wsj_acceptedEventTime), OBJC_ASSOCIATION_RETAIN_NONATOMIC); } + (void)load { Method a = class_getInstanceMethod(self, @selector(sendAction:to:forEvent:)); Method b = class_getInstanceMethod(self, @selector(__wsj_sendAction:to:forEvent:)); method_exchangeImplementations(a, b); } - (void)__wsj_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event { NSLog(@"%lf",NSDate.date.timeIntervalSince1970); NSLog(@"%lf",self.wsj_acceptedEventTime); if (NSDate.date.timeIntervalSince1970 - self.wsj_acceptedEventTime < self.wsj_acceptEventInterval) return; if (self.wsj_acceptEventInterval > 0) { self.wsj_acceptedEventTime = NSDate.date.timeIntervalSince1970; } [self __wsj_sendAction:action to:target forEvent:event]; } @end
实际使用起来就是这个样子
UIButton *tempBtn = [UIButton buttonWithType:UIButtonTypeCustom]; [tempBtn addTarget:self action:@selector(clickWithInterval:) forControlEvents:UIControlEventTouchUpInside]; tempBtn.wsj_acceptEventInterval = 0.5;
文章至此就结束了.虽然不推荐大范围用runtime, 但是小范围内使用还是可以解决不少小问题的.
相关文章推荐
- UITextAttributeTextColor 的替换方法+自定义导航控制器的价值
- RESideMeue使用观后感
- 关于UIImagePickerController
- druid配置
- iOS开发 UI--动画
- String baseprice = request.getParameter("baseprice")==null相关问题
- UE4 动画系统
- UE4 动画系统
- UIPopoverController
- iOS UI-团购案例(通过xib文件自定义UITableViewCell)
- iOS开发UI篇—懒加载
- UE4 创建第三人称角色
- UE4 创建第三人称角色
- Upgrade bank is empty or corrupted for FPC 0, please do standard upgrade sequence 错误解决&juniper 交换机系统升级
- java/scala优先队列(PriorityQueue)元素改变后如何实现有序
- 在iOS 8中使用UIAlertController
- iOS UI学习笔记(六)UIViewController
- uuid
- 在php环境中使用ueditor富文本编辑器步骤详解
- UISearchBar协议常用方法