IOS动态修改按钮响应时间

在项目开发中我们可能会遇到这样子的情况,比如在我们登陆的时候需要把数据发送给服务器进行比对,通常我们的做法是当用户点击按钮后,使用一个加载效果的view遮挡住当前界面,直到服务器返回数据或者超时。如果不进行遮挡,用户可能频繁的点击登录,而你又一直发送数据,这样子显然是不信的,解决这样子的方法有很多种。

今天我们说一种方式,让按钮响应时间由自己控制。
要想达到这种效果你可能需要去了解一下什么是 Runtime

OK,如果你不是很了解也没有关系,对于这个功能用到的也不多。其中包括:

 1 objc_getAssociatedObject(<#id object#>, <#const void *key#>)
 2 参数一:一般都是self,调用者
 3 参数二:你的key(key - value)
 4
 5
 6  有get方法那么肯定会有set
 7
 8 objc_setAssociatedObject(<#id object#>, <#const void *key#>, <#id value#>, <#objc_AssociationPolicy policy#>)
 9 参数一:self
10 参数二:key
11 参数三:value,这里要注意包装成为id类型对于int、float等基本类型
12 参数四:MRC基础的东西
13 /*
14 OBJC_ASSOCIATION_ASSIGN = 0,
15 OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1,
16 OBJC_ASSOCIATION_COPY_NONATOMIC = 3,
17 OBJC_ASSOCIATION_RETAIN = 01401,
18 OBJC_ASSOCIATION_COPY = 01403
19 */
20 为什么会用到上面的方法,因为在给一个Category动态添加属性。

完成了动态添加属性之后,我们需要利用Runtime的性质去对系统的方法动动手脚了。

这里我们还需要了解三个方法 分别是:

通过这个方法可以得到系统对象方法的编号,类型是Method
class_getInstanceMethod(<#__unsafe_unretained Class cls#>, <#SEL name#>)

通过这个方法可以获取到系统类方法的编号,类型是Method
class_getClassMethod(<#__unsafe_unretained Class cls#>, <#SEL name#>)

这里我们要获取到的是对象的方法,所以用第一个,在获取到系统的方法之后呢,我们需要定义一个自己的方法,用来和系统的方法进行互换

互换两个方法的编号
method_exchangeImplementations(<#Method m1#>, <#Method m2#>)

如图所示:互换前和互换后
交换前
交换后
所以我就达到了交换的目的。

了解了上面的几个方法之后,我们就可以开始 写代码了

首先如果想要使用Runtime第一步你得先导入:
  #import <objc/message.h>

第二步利用Runtime动态的去添加属性

这里要重写get set方法。
通过kvc赋值,所以我们先要有key,用来存/取数据

static char * const PQ_ACCEPTTIMEKEY = "pq_acceptTime";
static char * const PQ_DELAYINTERVALKEY = "pq_delayButtonInterVal";
// getter method
- (NSTimeInterval)pq_delayButtonInterVal{
return [objc_getAssociatedObject(self, PQ_DELAYINTERVALKEY) doubleValue];
}
- (NSTimeInterval)pq_acceptTime{
return [objc_getAssociatedObject(self, PQ_ACCEPTTIMEKEY) doubleValue];
}
// setter method
- (void)setPq_delayButtonInterVal:(NSTimeInterval)pq_delayButtonInterVal{
objc_setAssociatedObject(self, PQ_DELAYINTERVALKEY, @(pq_delayButtonInterVal), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (void)setPq_acceptTime:(NSTimeInterval)pq_acceptTime{
objc_setAssociatedObject(self, PQ_ACCEPTTIMEKEY, @(pq_acceptTime), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

完成动态添加属性之后,我们要把系统的方法和我们的方法进行互换,以便于添加功能。

 1 + (void)load{
 2 static dispatch_once_t onceToken;
 3 dispatch_once(&onceToken, ^{
 4 Method systemMethod = class_getInstanceMethod([self class], @selector(sendAction:to:forEvent:));
 5 Method myselfMethod = class_getInstanceMethod([self class], @selector(pq_sendAction:to:forEvent:));
 6 BOOL isAdd = class_addMethod([self class], @selector(sendAction:to:forEvent:), method_getImplementation(myselfMethod), method_getTypeEncoding(myselfMethod));
 7 if (!isAdd) {
 8 method_exchangeImplementations(systemMethod, myselfMethod);
 9 }
10 });
11 }

然后我们就要写自己的方法了,这里有一个小技巧把,先把系统的方法名打上,比如对于这个方法可以这样做:
1. 先输入 - sendAction 一般打到这里系统就会提示自动补全

2. 得到系统的方法名之后在前面添加我们的前缀,表示是我们自己的方法。比如

这里我就添加了一个前缀pq,再用下划线连接。
- (void)pq_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event

接下来就是处理代码的实现

 1 这里用到的两个变量一个需要对外公开(.h文件中),一个写在(.m文件中的)
 2 @interface UIControl ()
 3
 4 @property (nonatomic,assign) NSTimeInterval pq_acceptTime;
 5
 6 @end
 7
 8 - (void)pq_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event{
 9 if (NSDate.date.timeIntervalSince1970 - self.pq_acceptTime < self.pq_delayButtonInterVal) {
10 NSLog(@"现在点我我也不鸟你");
11 return;
12 }
13 if (self.pq_delayButtonInterVal > 0) {
14 self.pq_acceptTime = NSDate.date.timeIntervalSince1970;
15 }
16 [self pq_sendAction:action to:target forEvent:event];
17 }

至此,功能就完成啦,小伙伴们可以马上使用了

自己创建一个button,然后设置如下代码,如果你发现找不到你自己定义的属性,那么你一般是没有导入头文件在ViewController中
//设置这个延时时间是5秒钟
self.clickMeBtn.pq_delayButtonInterVal = 5;

到这里就全部完成啦,码字不容易,如果您觉得还行,麻烦顶一下!转载请注明出处,谢谢。

时间: 2024-08-29 05:42:57

IOS动态修改按钮响应时间的相关文章

ios动态修改指令

最近逆向个app,不想直接用ida修改app的指令,而是在执行过程中,用插件动态修改app的指令.经大神指点,大致是用mach_vm_protect 和mach_vm_write来操作,也在iosre.com上找到了类似源码,把代码放入了theos中,但每次执行make后,总是链接阶段报错:ld: symbol(s) not found for architecture armv7 似乎是找不到mach_vm_write 适合armv7的库文件.搞了好久都不行. 无奈,再来研究下源码的编译条件.

iOS 动态添加按钮

单击一个已有的按钮后自动创建一个新的按钮,并为新按钮添加事件,使得单击时弹出提示框. 在viewcontroller.h中添加 @property (weak, nonatomic) IBOutlet UIButton *addbutton; 为这个按钮添加响应事件addbutton 在viewcontroller.m中添加 - (IBAction)addButton:(id)sender { //动态添加一个按钮 CGRect frame = CGRectMake(0, 0, 300, 50)

iOS动态修改UILabel的宽度

sizeWithFont在ios7.0之后失效 cell.myCourse.text=cell_info.course; cell.myCourse.font=FONT; CGSize myCourseSize=[cell.myCourse.text sizeWithAttributes:[NSDictionary dictionaryWithObjectsAndKeys:cell.myCourse.font,NSFontAttributeName, nil]]; cell.myCourse.f

iOS常见问题之动态修改UINavigationController的rightBarButtonItem的title

1.初始化 在viewDidLoad里,为navigationItem添加名称为"添加分栏"的按钮 - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.navigationItem.rightBarButtonItem.title = @"添加分栏"; [self.navigationItem.rightBarButton

iOS-动态创建按钮

// // ViewController.m // 动态创建按钮 // // Created by YaguangZhu on 15/7/29. // Copyright (c) 2015年 YaguangZhu. All rights reserved. // #import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad {

iOS 动态更新

iOS 动态更新 App 动态更新 1.控件到 window 的层级关系: 2.分析控件的详细路径: 3.动态修改控件: 4.工具篇: 视图的层级关系: 每个 App , 至少有一个根 Window , 通常情况下我们只用一个 .window 有一个 rootViewController , 这就是我们所谓的根视图 , 我们所有的控制器都是放在 rootViewController 里面的. 这个是最简单的层级关系 如果在项目里有了这么一个路径 , 我们可以做什么呢? 在当项目很复杂 , 可以其

自己动手丰衣足食之轮播图一动态修改marginTop属性实现轮播图

引言 学习jQuery有年头了,刚开始学习时自己动手写过轮播图,放的久了以至于忘了大致思路了.现在转而做前端,抽空把jquery轮播图拿出来写一写,把各种思路都自己练习练习,这里主要使用动态修改marginTop来实现. 实现原理 1.除第一张图片外,其余图片全部隐藏,4张图片重叠起来. 2.导航按钮添加mouseover和mouseleave事件. 3.设置interval函数,启动定时器调用ShowImg函数. 4.动态修改marginTop属性达到上下轮播的效果,说道动态修改margin属

利用Mono.Cecil动态修改程序集来破解商业组件(仅用于研究学习)

原文:利用Mono.Cecil动态修改程序集来破解商业组件(仅用于研究学习) Mono.Cecil是一个强大的MSIL的注入工具,利用它可以实现动态创建程序集,也可以实现拦截器横向切入动态方法,甚至还可以修改已有的程序集,并且它支持多个运行时框架上例如:.net2.0/3.5/4.0,以及silverlight程序 官方地址:http://www.mono-project.com/Cecil 首先,我先假想有一个这样的商业组件,该组件满足了以下条件: 1. 该程序集的代码被混淆过了 2. 该程序

[SAP ABAP开发技术总结]动态修改选择屏幕

声明:原创作品,转载时请注明文章来自SAP师太博客,并以超链接形式标明文章原始出处,否则将追究法律责任!原文出自: 12.16.             动态修改屏幕 选择屏幕.对话屏幕都有对应的SCREEN内表,下面是几个重要属性: NAME:Name of the screen field.如果参数是select-options类型参数,则参数名以LOW与HIGH后缀来区分. GROUP1:选择屏幕元素通过 MODIF ID 选项设置GROUP1(对话屏幕通过属性设置),将屏幕元素分为一组,