博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS小技巧:用runtime 解决UIButton 重复点击问题
阅读量:4513 次
发布时间:2019-06-08

本文共 2284 字,大约阅读时间需要 7 分钟。

http://www.cocoachina.com/ios/20150911/13260.html

 

作者: 授权本站转载。

什么是这个问题

我们的按钮是点击一次响应一次, 即使频繁的点击也不会出问题, 可是某些场景下还偏偏就是会出问题.

通常是如何解决

我们通常会在按钮点击的时候设置这个按钮不可点击. 等待0.xS的延时后,在设置回来; 或者在操作结束的时候设置可以点击.

1
2
3
4
5
6
- (IBAction)clickBtn1:(UIbutton *)sender
{
    
sender.enabled = NO;
    
doSomething
    
sender.enabled = YES;
}

如果涉及到按钮不同状态不同样式的时候, 用enabled不见得够用.还得额外加个变量来记录状态.

1
2
3
4
5
6
7
- (IBAction)clickBtn1:(UIbutton *)sender
{
    
if 
(doingSomeThing) 
return
;
    
doingSomeThing = YES;
    
doSomething
    
doingSomeThing = NO;
}

笔者举的例子是直接在响应事件的周期内直接禁止点击的. 如果想做1秒内禁止重复点击的话,则得用performSelector:withObject:afterDelay:

漂亮的解决是怎样的

有了重复的代码段就是有了一个共性, 就可以抽象出来.

我们可以给按钮添加一个属性重复点击间隔, 通过设置这个属性来控制再次接受点击事件的时间间隔.

1
2
3
4
5
6
7
8
9
10
11
12
@interface UIControl (XY)
@property (nonatomic, assign) NSTimeInterval uxy_acceptEventInterval;   
// 可以用这个给重复点击加间隔
@end
static const char *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);
}

在app启动的时候,我们hook 所有的按钮的 event

1
2
3
4
5
6
7
8
@implementation UIControl (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)action to:(id)target forEvent:(UIEvent *)event
{
    
if 
(self.uxy_ignoreEvent) 
return
;
    
if 
(self.uxy_acceptEventInterval > 0)
    
{
        
self.uxy_ignoreEvent = YES;
        
[self performSelector:@selector(setUxy_ignoreEvent:) withObject:@(NO) afterDelay:self.uxy_acceptEventInterval];
    
}
    
[self __uxy_sendAction:action to:target forEvent:event];
}

实际使用起来就是这个样子

1
2
3
    
UIButton *tempBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    
[tempBtn addTarget:self action:@selector(clickWithInterval:) forControlEvents:UIControlEventTouchUpInside];
    
tempBtn.uxy_acceptEventInterval = 0.5;

文章至此就结束了.虽然不推荐大范围用runtime, 但是小范围内使用还是可以解决不少小问题的.

版权声明:本文为博主原创文章,未经博主允许不得转载。

 
 

转载于:https://www.cnblogs.com/itlover2013/p/4800235.html

你可能感兴趣的文章
javascript修改html <b>标签里面的内容
查看>>
open live writer安装以及代码高亮、折叠插件安装
查看>>
消息队列
查看>>
POJ 1321 棋盘问题 dfs回溯
查看>>
org.apache.catalina.LifecycleException异常的处理
查看>>
C++转向C#的疑惑:难道C#中没有拷贝构造函数 ?[转]
查看>>
计算一个整数二进制中1的个数
查看>>
netdom join 错误:指定的域不存在,或无法联系。
查看>>
Android中Dialog的使用
查看>>
12/10/2015 校内测试:数列
查看>>
Android Activity接收Service发送的广播
查看>>
[Leetcode] Spiral Matrix | 把一个2D matrix用螺旋方式打印
查看>>
加速和监控国际网络
查看>>
亲历亚马逊、华为机器学习面试,原来考官想听到这些回答[转]
查看>>
【Flex】读取本地XML,然后XML数据转成JSON数据
查看>>
RecyclerView使用StaggeredGridLayoutManager布局的粘性头部实现
查看>>
Android 优雅的让Fragment监听返回键
查看>>
Android 数据库框架总结,总有一个适合你!
查看>>
Android 设置 横屏 竖屏
查看>>
Spring MVC兑现QQ第三方登录
查看>>