在实际业务场景中,如何防止用户暴力点击,从而弹出多个界面或者发送多次网络请求呢.
解决方案1: 控制UIButton的enabled属性并且加上一定的延时操作就可以了. 但是太啰嗦,不可取
- (void)buttonClicked:(UIButton *)sender {
sender.enabled = NO;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
sender.enabled = YES;
});
}
方案2: 考虑到运行时, 创建UIControl的分类, 新增点击间隔时间属性, 重写sendAction:to:forEvent方法
#import <UIKit/UIKit.h>
@interface UIControl (EMTimer)
// 重复点击间隔
@property (nonatomic, assign) NSTimeInterval duration;
@end
// .m实现
#import "UIControl+EMTimerl.h"
#import <objc/runtime.h>
static char * const duration = "durationKey";
static char * const eventUnavailableKey = "eventUnavailableKey";
@interface UIControl ()
@property (nonatomic, assign) BOOL eventUnavailable;
@end
@implementation UIControl (EMTimer)
+ (void)load {
// 方法交换
Method method = class_getInstanceMethod(self, @selector(sendAction:to:forEvent:));
Method qi_method = class_getInstanceMethod(self, @selector(qi_sendAction:to:forEvent:));
method_exchangeImplementations(method, qi_method);
}
#pragma mark - Action functions
- (void)qi_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event {
if (self.eventUnavailable == NO) {
self.eventUnavailable = YES;
[self qi_sendAction:action to:target forEvent:event];
[self performSelector:@selector(setEventUnavailable:) withObject:@(NO) afterDelay:self.duration];
}
}
#pragma mark - Setter & Getter functions
// 运行时增加属性,实现get,set方法
- (NSTimeInterval)duration {
return [objc_getAssociatedObject(self, duration) doubleValue];
}
- (void)setDuration:(NSTimeInterval)qi_eventInterval {
objc_setAssociatedObject(self, duration, @(qi_eventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (BOOL)eventUnavailable {
return [objc_getAssociatedObject(self, eventUnavailableKey) boolValue];
}
- (void)setEventUnavailable:(BOOL)eventUnavailable {
objc_setAssociatedObject(self, eventUnavailableKey, @(eventUnavailable), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end