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