在ios开发中,按钮是最常用的控件之一了,用于人机交互,
实际开发中我们用到按钮的次数也会很多,不过按钮也是有弊端的。
假如我们有一堆数据需要提交,form表单
当我们填完数据,点击注册时,网速慢的情况,尽管我们使用加载控件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
网友评论