iOS - UIButton连续点击事件控制

原创文章,如转请备注转载地址

只是给自己写一些觉得实用的内容

自己用过的两种方法:
  • enabled
  • Runtime

1.先来说一下enabled, enabled是UIButton的父类UIControl的一个属性,

default is YES. if NO, ignores touch events and subclasses may draw differently

简单的说就是UIButton的点击事件是否能够响应;

在实践项目开发中,有时候我们会点击某个按钮,进行网络请求的操作,在网路请求的过程中,按钮是不能再点击,不然会再进行一次网络请求。这时候可以使用 enabled 这个属性,来控制按钮的交互事件。

如下面代码:


UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.enabled = NO;  
[[ApiManager shareInstance] fetchDataWithCompletionHandle:^(id data, NSError *error) {
    btn.enabled = YES;
}];

复制代码

通过在合适的时机,设置按钮的enabled属性可以起到大部分的作用。

特殊需求

现在还是有另外一种需求,我在按钮点击后,几秒内,按钮都不让触发点击事件,这时候Runtime就要出马了。

接下来说第二种方式,来控制连续点击事件。

我们先断点在一个按钮的点击事件中,看看从点击到响应,执行了多少方法。

红框选中的


- (void)sendAction:(SEL)action to:(nullable id)target forEvent:(nullable UIEvent *)event;

- (void)sendActionsForControlEvents:(UIControlEvents)controlEvents;

复制代码

可以看出所有的UIKit中的控制,触发点击事件的时候都会执行

sendAction:to:forEvent:

这个方法。所有我们只需要在运行时期,在这个方法中添加一些时间限制,在受限时间期间,点击不做任何相应接口。

直接上代码: 自己写了一个UIButton的Category

UIButton+RepeatClickControl


//.h文件
#import <UIKit/UIKit.h>

@interface UIButton (RepeatClickControl)

@property (assign, nonatomic) NSTimeInterval noClickInterval;

@end

//.m文件
#import "UIButton+RepeatClickControl.h"
#import <objc/runtime.h>

static const NSTimeInterval defautltTimeInterval = 1.0;

@interface UIButton()

@property (assign, nonatomic) BOOL isIngoreClick;  //不顾点击

@end

@implementation UIButton (RepeatClickControl)

+ (void)load
{
    //Method Swizzling
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
    
        /*
         struct objc_method {
         SEL _Nonnull method_name                                 OBJC2_UNAVAILABLE;
         char * _Nullable method_types                            OBJC2_UNAVAILABLE;
         IMP _Nonnull method_imp                                  OBJC2_UNAVAILABLE;
         }
         */
        //获取方法
        SEL defaultButtonActionSEL = @selector(sendAction:to:forEvent:);
        SEL changeButtonActionSEL = @selector(mySendAction:to:forEvent:);
        Method defaultButtonActionMethod = class_getInstanceMethod(self, defaultButtonActionSEL);
        Method changeButtonActionMethod = class_getInstanceMethod(self, changeButtonActionSEL);
        
        //添加方法
        BOOL isAdd = class_addMethod(self, defaultButtonActionSEL, method_getImplementation(changeButtonActionMethod), method_getTypeEncoding(changeButtonActionMethod));
        
        if ( isAdd ) {
            //添加成功,那么就替换实现方法
            class_replaceMethod(self, changeButtonActionSEL, method_getImplementation(defaultButtonActionMethod), method_getTypeEncoding(defaultButtonActionMethod));
        } else {
            //添加不成功,说明已经有方法了,那么直接执行方法实现的对调
            method_exchangeImplementations(defaultButtonActionMethod, changeButtonActionMethod);
        }
        
    });
}

- (void)mySendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event
{
    
    if ( [NSStringFromClass([self class]) isEqualToString:@"UIButton"] ) {
        if ( self.isIngoreClick ) {
            //不能点击
            return;
        } else {
            self.noClickInterval = (self.noClickInterval == 0) ? defautltTimeInterval : self.noClickInterval;
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.noClickInterval * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                self.isIngoreClick = NO;
            });
        }
    
    }
    
    self.isIngoreClick = YES;
    //这里并不会造成死循环,因为已经替换实现方法了
    [self mySendAction:action to:target forEvent:event];
}


#pragma mark - AssociatedObject

- (void)setNoClickInterval:(NSTimeInterval)noClickInterval
{
    objc_setAssociatedObject(self, @selector(noClickInterval), @(noClickInterval), OBJC_ASSOCIATION_ASSIGN);
}

- (NSTimeInterval)noClickInterval
{
    return [objc_getAssociatedObject(self, @selector(noClickInterval)) doubleValue];
}

- (void)setIsIngoreClick:(BOOL)isIngoreClick
{
    objc_setAssociatedObject(self, @selector(isIngoreClick), @(isIngoreClick), OBJC_ASSOCIATION_ASSIGN);
}

- (BOOL)isIngoreClick
{
    return [objc_getAssociatedObject(self, @selector(isIngoreClick)) boolValue];
}

@end

复制代码

直接创建放到项目中接口使用,至于自己要限制多少秒可以进行手动设置,默认是1秒内不能连续点击。 手动设置的话,如下代码即可:

UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.noClickInterval = 4.0;
其余初始化就省略,直接设置 noClickInterval 即可;
复制代码
我还会再回来了。我是卤蛋有点黑。再见。

转载于:https://juejin.im/post/5a96443c6fb9a06340523e63

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值