二、使用runtime实现防止按钮重复点击
2017-12-04 本文已影响56人
移动端_小刚哥
快速点击按钮,button响应方法可能触发多次。如果button的响应方法涉及到跳转的话,那么就会跳转多次。涉及到money的话账户有可能对不上。毕竟单身二十余年的手速不容小觑。废话结束
- 比较简单的解决方案可以在btn响应方法中添加timer,自己看看NSTimer就可以了,这里不做过多介绍。
- 使用runtime解决
#import <objc/runtime.h>
1. 给category设置时长
2. 记录每次点击按钮时的时间戳
3. 当前点击时的时间戳减去上次点击时的时间戳之差和可重复点击时长做比较,判断是否可以触发
简单粗暴的代码
//
// UIControl+JZG.h
// runtimeTest
//
// Created by 纪志刚 on 2017/11/29.
// Copyright © 2017年 纪志刚. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIControl (JZG)
@property (nonatomic, assign) NSTimeInterval jzg_acceptEventInterval; // 设置重复点击的时间间隔
@end
//
// UIControl+JZG.m
// runtimeTest
//
// Created by 纪志刚 on 2017/11/29.
// Copyright © 2017年 纪志刚. All rights reserved.
//
#import "UIControl+JZG.h"
#import <objc/runtime.h>
static const char *UIControl_acceptEventInterval = "UIControl_acceptEventInterval";
static const char *jzg_Inteval = "jzg_Inteval";
@interface UIControl ()
@property (nonatomic, assign) NSTimeInterval jzgInteval; // 记录点击时的时间戳
@end
@implementation UIControl (JZG)
/**
加载是截取UIControl的响应方法并指向自定义方法
*/
+ (void)load
{
Method a = class_getInstanceMethod(self, @selector(sendAction:to:forEvent:));
Method b = class_getInstanceMethod(self, @selector(jzg_sendAction:to:forEvent:));
method_exchangeImplementations(a, b);
}
/**
获取设置的点击时间间隔
@return 时间间隔
*/
- (NSTimeInterval)jzg_acceptEventInterval
{
return [objc_getAssociatedObject(self, UIControl_acceptEventInterval) doubleValue];
}
/**
设置点击时间间隔
@param uxy_acceptEventInterval <#uxy_acceptEventInterval description#>
*/
- (void)setJzg_acceptEventInterval:(NSTimeInterval)uxy_acceptEventInterval
{
objc_setAssociatedObject(self, UIControl_acceptEventInterval, @(uxy_acceptEventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
/**
获取上次点击的时候的时间戳
@return 时间戳
*/
-(NSTimeInterval)jzgInteval
{
return [objc_getAssociatedObject(self, jzg_Inteval) doubleValue];
}
/**
设置点击时的时间戳
@param jzgInteval 时间戳
*/
-(void)setJzgInteval:(NSTimeInterval)jzgInteval
{
objc_setAssociatedObject(self, jzg_Inteval, @(jzgInteval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
/**
自定义的响应方法,在此判断当前是否可触发UIControl的响应方法
@param action <#action description#>
@param target <#target description#>
@param event <#event description#>
*/
- (void)jzg_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event
{
if (NSDate.date.timeIntervalSince1970 - self.jzgInteval >= self.jzg_acceptEventInterval) {//可触发方法
[self jzg_sendAction:action to:target forEvent:event];
}
self.jzgInteval = NSDate.date.timeIntervalSince1970;
}
@end
objc_setAssociatedObject用于给对象添加关联对象,传nil可以移除相关的关联对象。
objc_getAssocicatedObject用于获取关联对象的值。
objc_removeAssociatedObject用于移除该对象的所有关联对象。如果打算只移除一部分则不能使用该方法。
关联策略
OBJC_ASSOCIATION_ASSIGN 等价于 @property(assign)。
OBJC_ASSOCIATION_RETAIN_NONATOMIC等价于 @property(strong, nonatomic)。
OBJC_ASSOCIATION_COPY_NONATOMIC等价于@property(copy, nonatomic)。
OBJC_ASSOCIATION_RETAIN等价于@property(strong,atomic)。
OBJC_ASSOCIATION_COPY等价于@property(copy, atomic)。