iOS runtime 相关实例

避免按钮快速点击多次相应问题

  • 创建UIButton 分类
1
2
3
4
5
6
7
8
9
10
11
12
//
// UIButton+time.h
//

#import <UIKit/UIKit.h>

@interface UIButton (time)

/* 防止button重复点击,设置间隔 */
@property (nonatomic, assign) NSTimeInterval acceptEventInterval;

@end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
//
// UIButton+time.m
//

#import "UIButton+time.h"
#import <objc/runtime.h>

@implementation UIButton (time)

static const char *UIButton_acceptEventInterval = "UIButton_acceptEventInterval";
static const char *UIButton_acceptEventTime = "UIButton_acceptEventTime";

// get方法 获取时间间隔
- (NSTimeInterval)acceptEventInterval{
return [objc_getAssociatedObject(self, UIButton_acceptEventInterval) doubleValue];
}

// set方法 赋值时间间隔
- (void)setAcceptEventInterval:(NSTimeInterval)mm_acceptEventInterval{
objc_setAssociatedObject(self, UIButton_acceptEventInterval, @(mm_acceptEventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

// get方法 获取时间
- (NSTimeInterval)acceptEventTime{
return [objc_getAssociatedObject(self, UIButton_acceptEventTime) doubleValue];
}

// set方法 赋值时间
- (void)setAcceptEventTime:(NSTimeInterval)mm_acceptEventTime{
objc_setAssociatedObject(self, UIButton_acceptEventTime, @(mm_acceptEventTime), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

/**
class_addMethod:如果发现方法已经存在,会失败返回,也可以用来做检查用,我们这里是为了避免源方法没有实现的情况;如果方法没有存在,我们则先尝试添加被替换的方法的实现
1.如果返回成功:则说明被替换方法没有存在.也就是被替换的方法没有被实现,我们需要先把这个方法实现,然后再执行我们想要的效果,用我们自定义的方法去替换被替换的方法. 这里使用到的是'class_replaceMethod'这个方法. class_replaceMethod本身会尝试调用class_addMethod和method_setImplementation,所以直接调用class_replaceMethod就可以了)
2.如果返回失败:则说明被替换方法已经存在.直接将两个方法的实现交换即
*/
//分类中重写load方法,实现方法的交换(只要能让其执行一次方法交换语句,load再合适不过了)
+ (void)load{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//获取这两个方法
Method systemMethod = class_getInstanceMethod(self, @selector(sendAction:to:forEvent:));
SEL sysSEL = @selector(sendAction:to:forEvent:);

Method myMethod = class_getInstanceMethod(self, @selector(mm_sendAction:to:forEvent:));
SEL mySEL = @selector(mm_sendAction:to:forEvent:);

//添加方法进去
BOOL isAddMethod = class_addMethod(self, sysSEL, method_getImplementation(myMethod), method_getTypeEncoding(myMethod));
//如果添加方法成功
if (isAddMethod) {
class_replaceMethod(self, mySEL, method_getImplementation(systemMethod), method_getTypeEncoding(systemMethod));
}else{
method_exchangeImplementations(systemMethod, myMethod);
}
});
/*-----以上主要是实现两个方法的互换,load是gcd的只shareinstance,果断保证执行一次-------*/
}

- (void)mm_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event{
if ([NSDate date].timeIntervalSince1970 - self.acceptEventTime < self.acceptEventInterval) {
return;
}

if (self.acceptEventInterval > 0) {
self.acceptEventTime = [NSDate date].timeIntervalSince1970;
}

[self mm_sendAction:action to:target forEvent:event];
}

@end
-------------本文结束感谢您的阅读-------------
最近的文章

iOS 接入Twitter 相关注意点

1. 接入前配置 Download and unzip Twitter Kit Add TwitterKit to “Embedded Binaries” in your Xcode project settings(测试发现不添加也可以) Add TwitterKit and TwitterCo …

继续阅读
更早的文章

c++传递字符串给c#使用问题

C++里,字符串要占用内存的。C++创建字符串,并传给C#,就会造成内存泄露(因为C#不知道C++如何创建,也就不知道如何销毁)。因此,通常的做法(甚至是C++互相调用的惯例),是 调用者(这里是C#)准备好一段内存缓冲区(这里是StringBuilder); 被调用者C++把字符串内容,填充到指 …

继续阅读