您的位置:首页 > 产品设计 > UI/UE

用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, 但是小范围内使用还是可以解决不少小问题的.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: