iOS Button连按处理防止按钮连续点击

简介: iOS Button连按处理防止按钮连续点击

前言


需求介绍:很多时候我们不希望按钮多次连按,如果去写Enabled略显麻烦,这里提供一种控制按钮点击间隔时间的方法,我已封装方便使用


GitHub地址:KJCategories


API


/* ******************这两个属性互斥********************/
/// 接受点击事件的时间间隔
@property (nonatomic, assign) NSTimeInterval kj_AcceptEventTime;
/// 接受点击事件执行处理之后的时间间隔
@property (nonatomic, assign) NSTimeInterval kj_AcceptDealTime;
/* ******************这两个属性互斥********************/


Runtime方法交换


内部以Category的方式实现,考虑到侵入性问题,所以没有将方法交换放在load里面,而是选择以委托(KJButtonTimeExchangeMethodProtocol)的形式,内部采用 dispatch_once 的方式保证只调用一次

@protocol KJButtonTimeExchangeMethodProtocol <NSObject>
@required
/// 是否开启时间间隔的方法交换
+ (void)kj_openTimeExchangeMethod;
@end

可以选择在任何你要使用属性kj_AcceptEventTimekj_AcceptDealTime 之前调用即可,例如viewDidLoad

[UIButton kj_openTimeExchangeMethod];

其实就是交换方法 sendAction:to:forEvent:,在 kj_sendAction:to:forEvent: 当中判断时间间隔

/// 交换方法后实现
- (void)kj_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event{
    if (self.kj_AcceptEventTime <= 0 && self.kj_AcceptDealTime <= 0) {
        [self kj_sendAction:action to:target forEvent:event];
        return;
    }
    NSTimeInterval time = self.kj_AcceptEventTime > 0 ? self.kj_AcceptEventTime : self.kj_AcceptDealTime;
    BOOL boo = (CFAbsoluteTimeGetCurrent() - self.kLastTime >= time);
    if (self.kj_AcceptEventTime > 0) {
        self.kLastTime = CFAbsoluteTimeGetCurrent();
    }
    if (boo) {
        if (self.kj_AcceptDealTime > 0) {
            self.kLastTime = CFAbsoluteTimeGetCurrent();
        }
        [self kj_sendAction:action to:target forEvent:event];
    }
}
如不需要点击事件间隔处理了,只需要将 kj_AcceptEventTimekj_AcceptDealTime 两个属性值设置为非正数即可


实现


//
//  UIButton+KJBlock.m
//  KJEmitterView
//
//  Created by 杨科军 on 2019/4/4.
//  Copyright © 2019 杨科军. All rights reserved.
//  https://github.com/yangKJ/KJExtensionHandler
#import "UIButton+KJBlock.h"
#import <objc/runtime.h>
@implementation UIButton (KJBlock)
static char kParameterTag;
/// 添加点击事件,默认UIControlEventTouchUpInside
- (void)kj_addAction:(KJButtonBlock)block{
    objc_setAssociatedObject(self, &kParameterTag, block, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    [self addTarget:self action:@selector(action:) forControlEvents:UIControlEventTouchUpInside];
}
/// 添加事件
- (void)kj_addAction:(KJButtonBlock)block forControlEvents:(UIControlEvents)controlEvents{
    objc_setAssociatedObject(self, &kParameterTag, block, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    [self addTarget:self action:@selector(action:) forControlEvents:controlEvents];
}
/// 事件响应方法
- (void)action:(UIButton*)sender{
    KJButtonBlock block = objc_getAssociatedObject(self, &kParameterTag);
    if (block) block(self);
}
#pragma mark - 时间相关方法交换
/// 是否开启时间间隔的方法交换
+ (void)kj_openTimeExchangeMethod{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        SEL originalSelector = @selector(sendAction:to:forEvent:);
        SEL swizzledSelector = @selector(kj_sendAction:to:forEvent:);
        Class clazz = [self class];
        Method originalMethod = class_getInstanceMethod(clazz, originalSelector);
        Method swizzledMethod = class_getInstanceMethod(clazz, swizzledSelector);
        BOOL boo = class_addMethod(clazz, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
        if (boo) {
            class_replaceMethod(clazz, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
        }else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    });
}
/// 交换方法后实现
- (void)kj_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event{
    if (self.kj_AcceptEventTime <= 0 && self.kj_AcceptDealTime <= 0) {
        [self kj_sendAction:action to:target forEvent:event];
        return;
    }
    NSTimeInterval time = self.kj_AcceptEventTime > 0 ? self.kj_AcceptEventTime : self.kj_AcceptDealTime;
    BOOL boo = (CFAbsoluteTimeGetCurrent() - self.kLastTime >= time);
    if (self.kj_AcceptEventTime > 0) {
        self.kLastTime = CFAbsoluteTimeGetCurrent();
    }
    if (boo) {
        if (self.kj_AcceptDealTime > 0) {
            self.kLastTime = CFAbsoluteTimeGetCurrent();
        }
        [self kj_sendAction:action to:target forEvent:event];
    }
}
- (NSTimeInterval)kj_AcceptEventTime{
    return [objc_getAssociatedObject(self, @selector(kj_AcceptEventTime)) doubleValue];
}
- (void)setKj_AcceptEventTime:(NSTimeInterval)kj_AcceptEventTime{
    objc_setAssociatedObject(self, @selector(kj_AcceptEventTime), @(kj_AcceptEventTime), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSTimeInterval)kj_AcceptDealTime{
    return [objc_getAssociatedObject(self, @selector(kj_AcceptDealTime)) doubleValue];
}
- (void)setKj_AcceptDealTime:(NSTimeInterval)kj_AcceptDealTime{
    objc_setAssociatedObject(self, @selector(kj_AcceptDealTime), @(kj_AcceptDealTime), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSTimeInterval)kLastTime{
    return [objc_getAssociatedObject(self, @selector(kLastTime)) doubleValue];
}
- (void)setKLastTime:(NSTimeInterval)kLastTime{
    objc_setAssociatedObject(self, @selector(kLastTime), @(kLastTime), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end

粗略封装,望大神帮助修改完善


备注:本文用到的部分函数方法和Demo,均来自三方库**KJCategories**,如有需要的朋友可自行pod 'KJCategories'引入即可


Button处理介绍就到此完毕,后面有相关再补充,写文章不容易,还请点个**小星星**传送门

相关文章
|
7月前
|
iOS开发
iOS MFMessageComposeViewController不显示取消按钮,导航条上白色,无取消按钮,无法返回应用...
iOS MFMessageComposeViewController不显示取消按钮,导航条上白色,无取消按钮,无法返回应用...
28 0
|
7月前
|
Web App开发 安全 JavaScript
关于 Safari back 按钮在 iOS 16 不能按照期望工作的问题分析
关于 Safari back 按钮在 iOS 16 不能按照期望工作的问题分析
51 0
|
Web App开发 安全 JavaScript
关于 Safari back 按钮在 iOS 16 不能按照期望工作的问题分析
关于 Safari back 按钮在 iOS 16 不能按照期望工作的问题分析
118 0
|
监控 Android开发 iOS开发
Android6.0 源码修改之 仿IOS添加全屏可拖拽浮窗返回按钮
Android6.0 源码修改之 仿IOS添加全屏可拖拽浮窗返回按钮
104 0
|
前端开发 JavaScript Android开发
【前端】IOS微信浏览器点击右上角遮罩实现
现在有一个需求,通过公众号或者链接,下载app应用,大家都知道,安卓和ios下载对应的版本都不一样。并且,ios 微信浏览器不支持应用下载,需要实现一个遮罩功能,提示用户通过浏览器下载,效果如下:
136 0
【前端】IOS微信浏览器点击右上角遮罩实现
|
API iOS开发 Perl
ios UIButton点击快捷回调
ios UIButton点击快捷回调
iOS--设置系统导航栏右上角按钮不显示问题
iOS--设置系统导航栏右上角按钮不显示问题
196 0
|
iOS开发
iOS开发 --重写UISearchBar的时候,点击取消searchbar会变深色,一闪而过
iOS开发 --重写UISearchBar的时候,点击取消searchbar会变深色,一闪而过
104 0
|
开发工具 iOS开发 git
iOS开发 - 类似美团选商品页,从按钮上往上滑动,tableview依然响应,点击按钮,按钮也可响应
iOS开发 - 类似美团选商品页,从按钮上往上滑动,tableview依然响应,点击按钮,按钮也可响应
172 0
iOS开发 - 类似美团选商品页,从按钮上往上滑动,tableview依然响应,点击按钮,按钮也可响应
|
iOS开发
iOS中CollectionView由于多次点击造成错误的解决方案
iOS中CollectionCiew由于多次点击,会给程序造成错误。 这个时候,我们可以用过手势类来进行判断和过滤。 但是,有一个快捷的解决方法,那就是给用户响应增加延时操作。 具体代码如下: [collectionView setUserInteractionEnabled:NO]; ...
871 0