-
Notifications
You must be signed in to change notification settings - Fork 8
Open
Description
Method Swizzling 在实际开发中用得还是蛮多的:
- 在开源库AFNetworking就使用了Method Swizzling将
将 NSURLSessionTask 的 resume 和 suspend 方法做了替换。替换的目的就是在这两个方法调用的时候发送暂停恢复的通知。 - Aspect 和JSPatch 里面会通过Method Swizzling 来替换系统的 forwardInvocation 在这里重新修改消息分发的规则。
在实际开发中可以用于:
- 防止数组取值时越界crash
#import "NSArray+Safe.h"
#import <objc/runtime.h>
@implementation NSArray (Safe)
+ (void)load {
// objectAtIndex: 方式取元素
Method originMethod = class_getInstanceMethod(objc_getClass("__NSArrayI"), @selector(objectAtIndex:));
Method replacedMethod = class_getInstanceMethod(objc_getClass("__NSArrayI"), @selector(safeObjectAtIndex:));
method_exchangeImplementations(originMethod, replacedMethod);
//......
// 直接通过数组下标的方式取元素
Method originMethodBySub = class_getInstanceMethod(objc_getClass("__NSArrayI"), @selector(objectAtIndexedSubscript:));
Method replacedMethodBySub = class_getInstanceMethod(objc_getClass("__NSArrayI"), @selector(safeObjectAtIndexedSubscript:));
method_exchangeImplementations(originMethodBySub, replacedMethodBySub);
//...
}
- (id)safeObjectAtIndex:(NSUInteger)index {
if (self.count > index && self.count) {
return [self safeObjectAtIndex:index];
}
return nil;
}
-(id)safeObjectAtIndexedSubscript:(NSUInteger)index {
if (self.count > index && self.count) {
return [self safeObjectAtIndexedSubscript:index];
}
return nil;
}
@end- 统计UIViewController加载次数
- 统计UIButton点击次数
- 统计自定义方法的执行
- 统计UITableView的Cell点击事件
- 处理按钮重复点击
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Method originMethod = class_getInstanceMethod(self, @selector(sendAction:to:forEvent:));
Method replacedMethod = class_getInstanceMethod(self, @selector(idl_SendAction:to:forEvent:));
method_exchangeImplementations(originMethod, replacedMethod);
});
}
- (void)idl_SendAction:(nonnull SEL)action to:(id)target forEvent:(UIEvent *)event {
if (self.delayTime > 0) {
if (self.userInteractionEnabled) {
[self idl_SendAction:action to:target forEvent:event];
}
self.userInteractionEnabled = NO;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
(int64_t)(self.delayTime * NSEC_PER_SEC)),
dispatch_get_main_queue(), ^{
self.userInteractionEnabled = YES;
});
}else{
[self idl_SendAction:action to:target forEvent:event];
}
}Metadata
Metadata
Assignees
Labels
No labels