iOS method swizz
1: 防止按钮在一定时间内重复响应默认1秒
1 // 2 // UIButton+AvoidDoubleClick.h 3 // 51WaywardShop 4 // 5 // Created by jisa on 2018/9/30. 6 // Copyright © 2018年 Anyike. All rights reserved. 7 // 8 9 #import <UIKit/UIKit.h> 10 11 NS_ASSUME_NONNULL_BEGIN 12 13 @interface UIButton (AvoidDoubleClick) 14 15 /** 16 避免多次点击重复响应。设置时间间隔(默认0.5S) 17 */ 18 @property (class, nonatomic, assign) NSTimeInterval intervalTime; 19 20 /** 21 上一次点击的时间 22 */ 23 @property (nonatomic, assign) NSTimeInterval clickTime; 24 @end 25 26 NS_ASSUME_NONNULL_END
1 // 2 // UIButton+AvoidDoubleClick.m 3 // 51WaywardShop 4 // 5 // Created by jisa on 2018/9/30. 6 // Copyright © 2018年 Anyike. All rights reserved. 7 // 8 9 #import "UIButton+AvoidDoubleClick.h" 10 #import <objc/runtime.h> 11 12 @implementation UIButton (AvoidDoubleClick) 13 14 + (void)load { 15 static dispatch_once_t onceToken; 16 dispatch_once(&onceToken, ^{ 17 UIButton.intervalTime = 1; 18 SEL systemSEL = @selector(sendAction:to:forEvent:); 19 Method systemMethod = class_getInstanceMethod([self class], systemSEL); 20 21 SEL customSEL = @selector(FF_sendAction:target:event:); 22 Method customMethod = class_getInstanceMethod(self, customSEL); 23 /// 防止子类没有重载父类的方法,找不到消息接收的对象。故使用方法交换时,通常配合,方法的添加和替换使用。 24 BOOL addSuccess = class_addMethod(self, systemSEL, method_getImplementation(customMethod), method_getTypeEncoding(customMethod)); 25 if (addSuccess) { 26 class_replaceMethod(self, customSEL, method_getImplementation(systemMethod), method_getTypeEncoding(systemMethod)); 27 }else { 28 method_exchangeImplementations(systemMethod, customMethod); 29 } 30 }); 31 } 32 33 34 #pragma mark -- method 35 - (void)FF_sendAction:(SEL)action target:(id)target event:(UIEvent *)event { 36 37 if (self.clickTime == 0) { 38 self.clickTime = [NSDate date].timeIntervalSince1970; 39 [self FF_sendAction:action target:target event:event]; 40 } 41 if ([NSDate date].timeIntervalSince1970 - self.clickTime < UIButton.intervalTime) { 42 return; 43 } 44 if (UIButton.intervalTime > 0) { 45 self.clickTime = [NSDate date].timeIntervalSince1970; 46 } 47 [self FF_sendAction:action target:target event:event]; 48 } 49 50 51 #pragma mark -- setter getter 52 + (void)setIntervalTime:(NSTimeInterval)intervalTime { 53 objc_setAssociatedObject(self, _cmd, @(intervalTime), OBJC_ASSOCIATION_RETAIN_NONATOMIC); 54 } 55 56 + (NSTimeInterval)intervalTime { 57 NSNumber *needNumber = objc_getAssociatedObject(self, @selector(setIntervalTime:)); 58 return [needNumber integerValue]; 59 } 60 61 - (void)setClickTime:(NSTimeInterval)clickTime { 62 objc_setAssociatedObject(self, _cmd, @(clickTime), OBJC_ASSOCIATION_RETAIN_NONATOMIC); 63 } 64 65 - (NSTimeInterval)clickTime { 66 NSNumber *num = objc_getAssociatedObject(self, @selector(setClickTime:)); 67 return [num integerValue]; 68 } 69 @end
2: 防止数组下标越界。
NSArray是一个抽象类。实际上使用的是“__NSArray0(空数组), __NSSingleObjectArrayI(只有一个元素的数组), __NSArrayI(超过两个元素的数组), __NSArrayM(可变数组)”。通过‘语法糖’获取元素时会走‘objectAtIndexedSubscript:’方法。
1 // 2 // NSArray+Crash.h 3 // NetWork 4 // 5 // Created by jisa on 2018/11/17. 6 // Copyright © 2018 jisa. All rights reserved. 7 // .h文件 8 9 #import <Foundation/Foundation.h> 10 11 NS_ASSUME_NONNULL_BEGIN 12 13 @interface NSArray (Crash) 14 15 @end 16 17 NS_ASSUME_NONNULL_END
1 // 2 // NSArray+Crash.m 3 // NetWork 4 // 5 // Created by jisa on 2018/11/17. 6 // Copyright © 2018 jisa. All rights reserved. 7 // 如果是一个空数组,即时'__NSArray0'时可以不用单独处理,会走'__NSSingleObjectArrayI'的方法。 8 9 #import "NSArray+Crash.h" 10 #import <objc/runtime.h> 11 12 @implementation NSArray (Crash) 13 + (void)load { 14 15 /* 数组 元素1个 */ 16 SEL oriSingleSEL = @selector(objectAtIndex:); 17 Method oriSingleMethod = class_getInstanceMethod(NSClassFromString(@"__NSSingleObjectArrayI"), oriSingleSEL); 18 SEL autoSingleSEL = @selector(FF_SingleObjectAtIndex:); 19 Method autoSingleMethod = class_getInstanceMethod(NSClassFromString(@"__NSSingleObjectArrayI"), autoSingleSEL); 20 21 if (class_addMethod(self, oriSingleSEL, method_getImplementation(autoSingleMethod), method_getTypeEncoding(autoSingleMethod))) { 22 class_replaceMethod(self, autoSingleSEL, method_getImplementation(oriSingleMethod), method_getTypeEncoding(oriSingleMethod)); 23 }else { 24 method_exchangeImplementations(oriSingleMethod, autoSingleMethod); 25 } 26 27 /* 数组 语法糖 元素1个 */ 28 SEL oriSingleTangSEL = @selector(objectAtIndexedSubscript:); 29 Method oriSingleTangMethod = class_getInstanceMethod(NSClassFromString(@"__NSSingleObjectArrayI"), oriSingleTangSEL); 30 SEL autoSingleTangSEL = @selector(FF_SingleTangObjectAtIndex:); 31 Method autoSingleTangMethod = class_getInstanceMethod(NSClassFromString(@"__NSSingleObjectArrayI"), autoSingleTangSEL); 32 if (class_addMethod(self, oriSingleTangSEL, method_getImplementation(autoSingleTangMethod), method_getTypeEncoding(autoSingleTangMethod))) { 33 class_replaceMethod(self, autoSingleTangSEL, method_getImplementation(oriSingleTangMethod), method_getTypeEncoding(oriSingleTangMethod)); 34 }else { 35 method_exchangeImplementations(oriSingleTangMethod, autoSingleTangMethod); 36 } 37 38 39 /* 数组 元素超过2 */ 40 SEL oriSEL = @selector(objectAtIndex:); 41 Method oriMethod = class_getInstanceMethod(NSClassFromString(@"__NSArrayI"), oriSEL); 42 SEL autoSEL = @selector(FF_ObjectAtIndex:); 43 Method autoMethod = class_getInstanceMethod(NSClassFromString(@"__NSArrayI"), autoSEL); 44 45 if (class_addMethod(self, oriSEL, method_getImplementation(autoMethod), method_getTypeEncoding(oriMethod))) { 46 class_replaceMethod(self, autoSEL, method_getImplementation(oriMethod), method_getTypeEncoding(oriMethod)); 47 }else { 48 method_exchangeImplementations(oriMethod, autoMethod); 49 } 50 51 /* 数组 语法糖 元素超过2 */ 52 SEL oriTangSEL = @selector(objectAtIndexedSubscript:); 53 Method oriTangMethod = class_getInstanceMethod(NSClassFromString(@"__NSArrayI"), oriTangSEL); 54 SEL autoTangSEL = @selector(FF_ObjectAtIndexSubscript:); 55 Method autoTangMethod = class_getInstanceMethod(NSClassFromString(@"__NSArrayI"), autoTangSEL); 56 if (class_addMethod(self, oriTangSEL, method_getImplementation(autoTangMethod), method_getTypeEncoding(autoTangMethod))) { 57 class_replaceMethod(self, autoTangSEL, method_getImplementation(oriTangMethod), method_getTypeEncoding(oriTangMethod)); 58 }else { 59 method_exchangeImplementations(oriTangMethod, autoTangMethod); 60 } 61 62 /* 可变数组 */ 63 SEL oriMSEL = @selector(objectAtIndex:); 64 Method oriMMethod = class_getInstanceMethod(NSClassFromString(@"__NSArrayM"), oriMSEL); 65 SEL autoMSEL = @selector(FF_MutableObjectAtIndex:); 66 Method autoMMethod = class_getInstanceMethod(NSClassFromString(@"__NSArrayM"), autoMSEL); 67 68 if (class_addMethod(self, oriMSEL, method_getImplementation(autoMMethod), method_getTypeEncoding(autoMMethod))) { 69 class_replaceMethod(self, autoMSEL, method_getImplementation(oriMMethod), method_getTypeEncoding(oriMMethod)); 70 }else { 71 method_exchangeImplementations(oriMMethod, autoMMethod); 72 } 73 74 /* 可变数组语法糖 */ 75 SEL oriMTangSEL = @selector(objectAtIndexedSubscript:); 76 Method oriMTangMethod = class_getInstanceMethod(NSClassFromString(@"__NSArrayM"), oriMTangSEL); 77 SEL autoMTangSEL = @selector(FF_MutableObjectAtIndexSubscript:); 78 Method autoMTangMethod = class_getInstanceMethod(NSClassFromString(@"__NSArrayM"), autoMTangSEL); 79 if (class_addMethod(self, oriMTangSEL, method_getImplementation(autoMTangMethod), method_getTypeEncoding(autoMTangMethod))) { 80 class_replaceMethod(self, autoMTangSEL, method_getImplementation(oriMTangMethod), method_getTypeEncoding(oriMTangMethod)); 81 }else { 82 method_exchangeImplementations(oriMTangMethod, autoMTangMethod); 83 } 84 85 86 } 87 88 #pragma mark -- method 89 - (id)FF_SingleObjectAtIndex:(NSInteger)index { 90 if (self.count - 1 < index || self.count == 0) { 91 @try { 92 return [self FF_SingleObjectAtIndex:index]; 93 } @catch (NSException *exception) { 94 NSLog(@"%@", exception.reason); 95 return nil; 96 } @finally { 97 NSLog(@"下标越界"); 98 } 99 }else { 100 return [self FF_SingleObjectAtIndex:index]; 101 } 102 } 103 104 105 - (id)FF_SingleTangObjectAtIndex:(NSInteger)index { 106 if (self.count - 1 < index || self.count == 0) { 107 @try { 108 return [self FF_SingleTangObjectAtIndex:index]; 109 } @catch (NSException *exception) { 110 NSLog(@"%@", exception.reason); 111 return nil; 112 } @finally { 113 NSLog(@"下标越界"); 114 } 115 }else { 116 return [self FF_SingleTangObjectAtIndex:index]; 117 } 118 } 119 120 121 - (id)FF_ObjectAtIndex:(NSInteger)index { 122 if (self.count - 1 < index || self.count == 0) { 123 @try { 124 return [self FF_ObjectAtIndex:index]; 125 } @catch (NSException *exception) { 126 NSLog(@"%@", exception.reason); 127 return nil; 128 } @finally { 129 NSLog(@"下标越界"); 130 } 131 }else { 132 return [self FF_ObjectAtIndex:index]; 133 } 134 } 135 136 - (id)FF_ObjectAtIndexSubscript:(NSInteger)index { 137 if (self.count - 1 < index || self.count == 0) { 138 @try { 139 return [self FF_ObjectAtIndexSubscript:index]; 140 } @catch (NSException *exception) { 141 NSLog(@"%@", exception.reason); 142 return nil; 143 } @finally { 144 NSLog(@"下标越界"); 145 } 146 }else { 147 return [self FF_ObjectAtIndexSubscript:index]; 148 } 149 } 150 151 - (id)FF_MutableObjectAtIndex:(NSInteger)index { 152 if (self.count - 1 < index || self.count == 0 ) { 153 @try { 154 return [self FF_MutableObjectAtIndex:index]; 155 } @catch (NSException *exception) { 156 NSLog(@"%@", exception.reason); 157 return nil; 158 } @finally { 159 NSLog(@"下标越界"); 160 } 161 }else { 162 return [self FF_MutableObjectAtIndex:index]; 163 } 164 } 165 166 - (id)FF_MutableObjectAtIndexSubscript:(NSInteger)index { 167 if (self.count - 1 < index || self.count == 0 ) { 168 @try { 169 return [self FF_MutableObjectAtIndexSubscript:index]; 170 } @catch (NSException *exception) { 171 NSLog(@"%@", exception.reason); 172 return nil; 173 } @finally { 174 NSLog(@"下标越界"); 175 } 176 }else { 177 return [self FF_MutableObjectAtIndexSubscript:index]; 178 } 179 } 180 181 @end