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

作者:uxyheaven 授权本站转载。

什么是这个问题

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

通常是如何解决

我们通常会在按钮点击的时候设置这个按钮不可点击. 等待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, 但是小范围内使用还是可以解决不少小问题的.

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

 
 

iOS小技巧:用runtime 解决UIButton 重复点击问题的更多相关文章

  1. iOS小技巧–用runtime 解决UIButton 重复点击问题

    什么是这个问题 我们的按钮是点击一次响应一次, 即使频繁的点击也不会出问题, 可是某些场景下还偏偏就是会出问题. 通常是如何解决 我们通常会在按钮点击的时候设置这个按钮不可点击. 等待0.xS的延时后 ...

  2. iOS小技巧 - 如何使UIView可以绑定点击事件

    让我们这次直接进入正题,有时候我们想做以下这种界面: 目前我就想到三种方案: 做一个tableview,然后组织cell的界面如上图所示 做一个button子类,使得button的界面能如上图所示 做 ...

  3. iOS小技巧总结,绝对有你想要的

    原文链接 在这里总结一些iOS开发中的小技巧,能大大方便我们的开发,持续更新. UITableView的Group样式下顶部空白处理 //分组列表头部空白处理 UIView *view = [[UIV ...

  4. iOS 为移动中的UIView(UIButton )添加点击事件

    高高兴兴迎接新的产品新需求,满心欢喜的开始工作,结果研究了一下午才发现,是自己想的太简单了,是我太单纯呀. 需求是这样的类似下雪的效果,随机产生一些小雪花,然后每个雪花可以点击到下个页面. 接到需求之 ...

  5. iOS开发小技巧--利用MJExtension解决数据结构复杂的模型转换

    一.开发中难免会遇到,系统返回的数据中字典套集合,集合里面又套一层字典,然后字典里面还有字典或者集合等等的复杂结构的数据...MJExtension轻松搞定这类问题 1.解决方法一: 例:百思项目中帖 ...

  6. iOS小技巧3

    将颜色合成图片 将颜色合成图片 +(UIImage *)imageWithColor:(UIColor *)color { CGRect rect = CGRectMake(0.0f, 0.0f, 1 ...

  7. iOS小技巧 - 和屏幕等宽的Table分割线

    前言 因为本人也是学习iOS才一个多月,在写程序的过程中经常会遇到一些看似应该很简单,但是要解决好却要知道一点小trick的问题. 因此后面会陆续记一些这类问题,一来加深印象,二来也可以做个备忘录. ...

  8. 总有你需要的之 ios 小技巧 (下)

    图片上绘制文字 写一个UIImage的category NSMutableParagraphStyle* paragraphStyle = [[NSParagraphStyle defaultPara ...

  9. 你想要的iOS 小技巧总结

    UITableView的Group样式下顶部空白处理 //分组列表头部空白处理 UIView *view = [[UIView alloc] initWithFrame:CGRectMake(, , ...

随机推荐

  1. react高阶函数组件

    Layout as a Higher Order Component // components/MyLayout.js import Header from './Header'; const la ...

  2. css3之弹性盒模型(Flex Box)

    CSS3 弹性盒子(Flex Box) 弹性盒子是 CSS3 的一种新的布局模式. CSS3 弹性盒( Flexible Box 或 flexbox),是一种当页面需要适应不同的屏幕大小以及设备类型时 ...

  3. Liferay 7:Liferay DXP解决方案

    分享是美德,欢迎探讨技术 这个作者很厉害呀,写的博客都是解决很刁钻问题的.强烈推荐 http://www.liferaysolution.com/2017/06/captcha-recaptcha-w ...

  4. stream的filter用法

    Person p1 = new Person("张三", new BigDecimal("23.0"));Person p2 = new Person(&quo ...

  5. Django项目:CRM(客户关系管理系统)--38--30PerfectCRM实现King_admin编辑自定义字段验证

    # kingadmin.py # ————————04PerfectCRM实现King_admin注册功能———————— from crm import models #print("ki ...

  6. CSS中position和header和overflow和background

    <!DOCTYPE html> <!--CSS中position属性--> <html lang="en"> <head> < ...

  7. bzoj 1266 [AHOI2006] 上学路线

    传送门 传说中的经典容斥+卢卡斯定理+中国剩余定理 题解传送门 //Achen #include<algorithm> #include<iostream> #include& ...

  8. [BZOJ2427][HAOI2010]软件安装-tarjan缩点-树上dp

    <题面> 这个题真伤人 之前Tarjan和树规都没学好,吃了不少亏,仔仔细细的搞了一天,收获颇丰 先来一个Tarjan的链接:$\mathbb{O}$ 题目的数据比较友好: $dp$不对: ...

  9. mysql8 navicat

    先把root账户的加密规则改回去 ALTER USER 'root'@'localhost' IDENTIFIED BY 'password' PASSWORD EXPIRE NEVER; 然后使用新 ...

  10. Comparator进行List集合排序

    对数据库中查询到的结果进行排序,一般开发中,实体类是没有实现Comparable接口的,所以不能实现compareTo()方法进行排序, 只能用Comparator去进行排序,只需要在带排序的集合中加 ...