原创文章,如转请备注转载地址
只是给自己写一些觉得实用的内容
自己用过的两种方法:
- 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 即可;
复制代码