美文网首页iOSiOS DevelopmentIos
Runtime优雅的解决UIButton多次点击(重复点击)

Runtime优雅的解决UIButton多次点击(重复点击)

作者: hnxyzhw | 来源:发表于2016-08-03 16:57 被阅读4239次

在实际开发中我们,点击一个button按键时,需要触发一个事件去执行。用户在正常操作情况下,单次点击时,button只会响应一次点击。但是如果用户多次点击一个button,那么就会引起这个事件被多次执行,导致一些bug的出现。
如何优雅解决的这个问题呢?今天我们来使用Runtime来解决UIButton重复点击的问题。
 首先新建一个分类category,继承于UIControl,名字自己定义。
 UIControl+ZHW.h(.h文件)

@interface UIControl (ZHW)
@property (nonatomic, assign) NSTimeInterval zhw_acceptEventInterval;//添加点击事件的间隔时间

@property (nonatomic, assign) BOOL zhw_ignoreEvent;//是否忽略点击事件,不响应点击事件
@end

UIControl+ZHW.m(.m文件)在使用runtime时,需要导入相应的库(objc/runtime.h)

@implementation UIControl (ZHW)
static const char *UIControl_acceptEventInterval = "UIControl_acceptEventInterval";

static const char *UIcontrol_ignoreEvent = "UIcontrol_ignoreEvent";

- (NSTimeInterval)zhw_acceptEventInterval {
    
    return [objc_getAssociatedObject(self, UIControl_acceptEventInterval) doubleValue];
    
}

- (void)setZhw_acceptEventInterval:(NSTimeInterval)zhw_acceptEventInterval {
    
    objc_setAssociatedObject(self, UIControl_acceptEventInterval, @(zhw_acceptEventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    
}

- (BOOL)zhw_ignoreEvent {
    
    return [objc_getAssociatedObject(self, UIcontrol_ignoreEvent) boolValue];
    
}

- (void)setZhw_ignoreEvent:(BOOL)zhw_ignoreEvent {
    
    objc_setAssociatedObject(self, UIcontrol_ignoreEvent, @(zhw_ignoreEvent), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    
}

+ (void)load {
    
    Method a = class_getInstanceMethod(self, @selector(sendAction:to:forEvent:));
    
    Method b = class_getInstanceMethod(self, @selector(__zhw_sendAction:to:forEvent:));
    
    method_exchangeImplementations(a, b);
    
}

- (void)__zhw_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event {
    
    if (self.zhw_ignoreEvent) return;
    
    if (self.zhw_acceptEventInterval > 0) {
        
        self.zhw_ignoreEvent = YES;
        
        [self performSelector:@selector(setZhw_ignoreEvent:) withObject:@(NO) afterDelay:self.zhw_acceptEventInterval];
        
    }
    
    [self __zhw_sendAction:action to:target forEvent:event];
    
}

@end

在需要用到地方导入UIControl+ZHW.h头文件设置button的点击时间间隔

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIButton *button;
@property (weak, nonatomic) IBOutlet UIView *colorView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.button.zhw_ignoreEvent = NO;
    self.button.zhw_acceptEventInterval = 3.0;
}
- (IBAction)runtimeAction:(UIButton *)sender {
    NSLog(@"----run click");
    [UIView animateWithDuration:3 animations:^{
        
        self.colorView.center = CGPointMake(200, 500);
        
    } completion:^(BOOL finished) {
        
        self.colorView.center = CGPointMake(95, 85);
        
    }];
}
- (IBAction)buttonAction:(UIButton *)sender {
    NSLog(@"------comm click");
    [UIView animateWithDuration:3 animations:^{
        
        self.colorView.center = CGPointMake(200, 500);
        
    } completion:^(BOOL finished) {
        
        self.colorView.center = CGPointMake(95, 85);
        
    }];
}

运行demo,可以发现button多次点击的问题得到了解决。在设置button的相应点击事件的时间间隔,在这个 间隔时间内,button只会响应一次点击事件。
 附上demo:UIButtonMutablieClick

相关文章

网友评论

  • Be_ingenious:tableview 左滑删除按钮 不管用了
  • 走停2015_iOS开发:ARC的环境下静态变量怎么设置
  • 折颜乀:同问楼上的这个问题
  • 拥抱月亮的大星星:http://www.jianshu.com/p/7bca987976bd 这篇文章很早就出来了,感觉你的是不是参考他的写的
    拥抱月亮的大星星:@hnxyzhw 哦,因为之前看过,一看你这个,思路一样:flushed::flushed::joy::joy:
    hnxyzhw:@拥抱月亮的大星星 我是参考开源中国上一位网友写的 :joy: ,关于runtime解决button的重复点击,你搜索一下就可看到有很多结果了,我只是记录整理了一下。
  • 6e62803aebc1:优雅么...

  • 183476642b07:如果UIButton的多次点击导致你的逻辑出现问题,你就应该重点去修改你的逻辑,而不是在按钮上做文章
    hnxyzhw:@拉风张 你的观点我不反对,我只是换一种解决问题的方式。解决button的重复点击,也可以使用button的select状态,来进行判断button的有效点击。
  • 小白e7899:如果有个设置全局按钮的重复点击的方法就更好,这样不管产品经理需求怎么办,都可以应对
    hnxyzhw:@小白e7899 你可以将头文件(UIControl+ZHW.h)导入你的.pch里,只要你创建button时,设置一下acceptEventInterval 点击的时间间隔,就可以了,已经很方便了。
  • c775c38ec028:要考虑过性能和维护问题,增加了很大不确定性。还有,出现点多次按钮说明本身设计就有问题,把问题隐藏反而造成更多的设计问题。
  • 溪枫狼:我用的也是这个思路,加到项目后发现影响了拍照按钮,另外我的tabbaritem用了button自定义,也受到了影响。后来加了个开启重复点击的属性,并且对相机按钮进行了过滤。
    溪枫狼:@hnxyzhw 系统的movieViewController也要过滤。目前就发现这两个系统的受影响
    hnxyzhw:@溪枫狼 如果说复用同一个button的话,我的思路跟你说的一样,就是添加一个开启重复点击的开关状态(openState),判断当前开关的状态,来处理是不是要屏蔽重复点击。
  • 39e11ca22198:我还是觉得解决思路不对,在Button上作文章既难懂,又容易出Bug
  • 大象飞:听说 用RAC更优雅
    大象飞:@hnxyzhw 嗯 嗯 可惜不太好学
    hnxyzhw:@大象飞 没有接触过你说的RAC :joy: 你说的是ReactiveCocoa响应式编程么?
  • zweic:实际情况是这样的,点击一次button后需要请求网络,在请求网络的时候不允许再点击,只有请求完成后才可。 你这里是一段时间后可以点击,但要是在这段时间里网络还没请求完怎么办呢
    2cc6b5825eab:遗留的问题是,我的button在当前场景设置了interval,我在其他场景不需要的时候,我需要重置,而且还不能忘,特别是多人项目
    zweic:@hnxyzhw ok 看到了
    hnxyzhw:@zweic 建议你使用这个属性zhw_ignoreEvent,当点击一次进行网络请求时,讲zhw_ignoreEvent重置为YES,当请求完成后,在将zhw_ignoreEvent重置为NO。也可以直接设置button.enabled属性来达到你所说的效果,(愿文档说明:@property(nonatomic,getter=isEnabled) BOOL enabled; // default is YES. if NO, ignores touch events and subclasses may draw differently)
  • zeroskylian:楼主,在set get 方法中关联是什么作用
    zeroskylian:@曾兆程 谢谢楼主,学到了
    我是Python小白:@zeroskylian 这里其实就是用runtime动态的给UIButton这个类添加两个属性zhw_acceptEventInterval & zhw_ignoreEvent . 在VC中控制button的zhw_ignoreEvent和zhw_acceptEventInterval属性的值来解决UIButton的多次点击
  • 我是Python小白:已经看懂了 .
    - (void)__zhw_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event {
    if (self.zhw_ignoreEvent) {
    return;
    }
    if (self.zhw_acceptEventInterval > 0) {
    self.zhw_ignoreEvent = YES;
    [self performSelector:@selector(setZhw_ignoreEvent:) withObject:@(NO) afterDelay:self.zhw_acceptEventInterval];
    }
    //这个地方执行的是系统的sendAction方法.
    [self __zhw_sendAction:action to:target forEvent:event];
    }
  • 我是Python小白: Method a = class_getInstanceMethod(self, @selector(sendAction:to:forEvent:));
    Method b = class_getInstanceMethod(self, @selector(__zhw_sendAction:to:forEvent:));
    method_exchangeImplementations(a, b);
  • 我是Python小白:请问下,楼主是怎么执行系统按钮的sendAction:to:forEvent:方法?
    hnxyzhw:@曾兆程 可以点击文章末尾的demo的链接下载查看。我在demo中使用的是storyboard,偷个懒 :grin:
  • pengrain:用这种方法也可解决问题
    [[self class] cancelPreviousPerformRequestsWithTarget:self selector:@selector(ChangeGoodsCount:) object:cell];
    [self performSelector:@selector(ChangeGoodsCount:) withObject:cell afterDelay:1];
    hnxyzhw:@pengrain 嗯,延时也是可以达到这种效果的。
  • 69ec07367c07:就活导致一下bug出现。感觉这里有小语病。。。
    hnxyzhw:@zhongqiu :grin: 谢谢关注已改,表达能力有限,看代码就好。
  • mark666:完美的解决了我的问题!
    mark666:@hnxyzhw 思路不错
    hnxyzhw:@mark666 造轮子而已 :flushed:
  • 凯文Kevin21:我虽然了解runtime,却不会应用它去解决问题。 :joy: :joy:
    hnxyzhw:@七秒小鱼人 解决这个问题的方式有多种,找到一种适合自己的方案就行,其他的就当是拓展学习了。
  • 蛮小刀:好
    hnxyzhw:@KKLater 过奖了,只是记录了下平时遇到的问题

本文标题:Runtime优雅的解决UIButton多次点击(重复点击)

本文链接:https://www.haomeiwen.com/subject/rvgqsttx.html