ios按钮重复点击那点事

2019-03-11  本文已影响0人  有梦才可以远航

在ios开发中,按钮是最常用的控件之一了,用于人机交互,
实际开发中我们用到按钮的次数也会很多,不过按钮也是有弊端的。

假如我们有一堆数据需要提交,form表单

应用截图.png
当我们填完数据,点击注册时,网速慢的情况,尽管我们使用加载控件MBProgressHUD,
但是重复点击按钮还是会响应多次,这样就会造成重复注册账号。

解决办法:

//  UIControl+recurClick.m
//  主要解决按钮的重复点击问题
//  本质为延时执行
//  按钮添加category

#import <UIKit/UIKit.h>

@interface UIControl (recurClick)

@property (nonatomic, assign) NSTimeInterval resumeEventInterval;//延时时间(单位:s)
@property (nonatomic, assign) BOOL ignoreEvent;//是否需要设置延时执行

@end
//  UIControl+recurClick.m
//  主要解决按钮的重复点击问题
//  本质为延时执行
//  利用runtime原理延时响应按钮点击

#import "UIControl+recurClick.h"
#import <objc/runtime.h>

static const char *UIControl_acceptEventInterval = "UIControl_resumeEventInterval";
static const void *BandNameKey = &BandNameKey;

@implementation UIControl (recurClick)
# pragma mark - set get
- (void)setResumeEventInterval:(NSTimeInterval)resumeEventInterval
{
    objc_setAssociatedObject(self, UIControl_acceptEventInterval, @(resumeEventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSTimeInterval)resumeEventInterval
{
    return [objc_getAssociatedObject(self, UIControl_acceptEventInterval) doubleValue];
}


- (void)setIgnoreEvent:(BOOL)ignoreEvent
{
    
    objc_setAssociatedObject(self, BandNameKey, [NSNumber numberWithBool:ignoreEvent], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (BOOL)ignoreEvent
{
    
    return [objc_getAssociatedObject(self, BandNameKey) boolValue];
}

#pragma mark -延时执行
+ (void)load
{
    
    SEL oldSelector = @selector(sendAction:to:forEvent:);
    SEL newSelector = @selector(__resume_sendAction:to:forEvent:);
    
    Method oldMethod = class_getInstanceMethod(self, oldSelector);
    Method newMethod = class_getInstanceMethod(self, newSelector);
    
    
    if (class_addMethod(self,
                        oldSelector,
                        method_getImplementation(newMethod),
                        method_getTypeEncoding(newMethod))) {
        class_replaceMethod(self,
                            newSelector,
                            method_getImplementation(oldMethod),
                            method_getTypeEncoding(oldMethod));
    } else {
        method_exchangeImplementations(oldMethod, newMethod);
    }
}
- (void)__resume_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event
{
    if (self.ignoreEvent){
        return;
    }
    if (self.resumeEventInterval > 0){
        self.ignoreEvent = YES;
        //GCD多线程延时执行
        dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.resumeEventInterval * NSEC_PER_SEC));
        dispatch_after(time, dispatch_get_main_queue(), ^{
            self.ignoreEvent = NO;
        });
    }
    [self __resume_sendAction:action to:target forEvent:event];
}

欢迎互相学习Github

上一篇下一篇

猜你喜欢

热点阅读