Objective-C Method Swizzling
来源:互联网 发布:linux 重启oracle 编辑:程序博客网 时间:2024/05/16 03:24
切入正题
Objective-C中的Hook又被称作 Method Swizzling ,这是动态语言都具有的特性。在Objective-C中经常会把Hook的逻辑写在 +load 方法中,有时候需要Hook子类和父类的同一个方法,但是它们的 +load 方法调用顺序不同。一个常见的顺序可能是:父类 ->子类 -> 子类类别 ->父类类别。所以Hook的顺序并不能保证,就不能保证Hook后方法调用的顺序是对的。而且使用不同方法Method Swizzing也会带来不同的结果。本文将会对这些情况下的Hook结果进行分析和总结。
Method Swizzling常用实现方案
方案A:如果类中没有实现Original selector对应的方法,那就先添加Method,并将其IMP映射为Swizzle的实现。然后替换Swizzle selector的IMP为Original的实现;否则交换二者IMP。
+(void)load { static dispatch_once_t onceToken; dispatch_once(&onceToken,^{ Class aClass = [self class]; SEL originalSelector = @selector(method_original:); SEL swizzledSelector = @selector(method_swizzle:); Method originalMethod = class_getInstanceMethod(aClass, originalSelector); Method swizzledMethod = class_getInstanceMethod(aClass, swizzledSelector); BOOL didAddMethod = class_addMethod(aClass, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod)); if(didAddMethod) { class_replaceMethod(aClass, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)); } else { method_exchangeImplementations(originalMethod, swizzledMethod); } });}
有时为了避免方法命名冲突和参数_cmd被篡改,也会使用下面这种静态方法版本的Method Swizzle。CaptainHook中的宏定义也是采用这种方式,比较推荐:
typedef IMP *IMPPointer;static void MethodSwizzle(id self,SEL _cmd, id arg1);static void (*MethodOriginal)(id self,SEL _cmd, id arg1);static void MethodSwizzle(id self, SEL _cmd, id arg1) { MethodOriginal(self,_cmd,arg1);}BOOL class_swizzleMethodAndStore(Class class, SEL original,IMP replacement, IMPPointer store) { IMP imp = NULL; Method method = class_getInstanceMethod(class, original); if(method) { const char *type = method_getTypeEncoding(method); imp = class_replaceMethod(class, original, replacement, type); if(!imp) { imp = method_getImplementation(method); } } if(imp && store) { *store = imp; } return (imp != NULL);}+(BOOL)swizzle:(SEL)original with:(IMP)replacement store:(IMPPointer)store { return class_swizzleMethodAndStore(self, original, replacement, store);}+(void)load { [self swizzle:@selector(originalMethod:) with:(IMP)MethodSwizzle store:(IMP *)&MethodOriginal];}
方案B
实质对方案A的缩减版:
+(void)load { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ Class aClass = [self class]; SEL originalSelector = @selector(method_original:); SEL swizzledSelector = @selector(method_swizzle:); Method originalMethod = class_getInstanceMethod(aClass, originalSelector); Method swizzledMethod = class_getInstanceMethod(aClass, swizzledSelector); method_exchangeImplementations(originalMethod, swizzledMethod); });}
直接交换IMP是很危险的。因为如果这个类中没有实现这个方法,class_getInstanceMethod()返回的是某个类的Method对象,这样method_exchangeImplementations()就把父类的原始方法实现(IMP)跟这个类的Swizzle实现交换。这样其他父类与其他子类的方法调用就会出现问题,最严重的就是crash。
0 0
- Objective-C Method Swizzling
- Objective-C Method Swizzling
- Objective-C Method Swizzling
- Objective-C Method Swizzling
- Objective-C Method Swizzling
- Objective-C中的Method Swizzling
- [iOS]Objective-C Method Swizzling
- Objective-C的hook方案: Method Swizzling
- Objective-C的hook方案: Method Swizzling
- Objective-C Method Swizzling 的最佳实践
- Objective-C Method Swizzling 的最佳实践
- Objective-c Method Swizzling的详细使用方法
- Objective-C Method Swizzling 的最佳实践
- Objective-C Runtime 运行时:Method Swizzling
- iOS安全–Objective-C Method Swizzling
- Objective-C Runtime :Method Swizzling - method_exchangeImplementations
- iOS安全–Objective-C Method Swizzling
- Objective-C Method Swizzling 的最佳实践
- 欢迎使用CSDN-markdown编辑器
- MongoDB基本语法
- C++set
- js实现往表格动态添加学生的学号、姓名、语数英的考试成绩和总分(总分不是填写),实现行与行之的颜色相间,高光的效果
- JAVAWEB开发之Spring详解之——AOP底层剖析(基于JDK和cglib)、Spring中的AOP以及基于AspectJ的AOP实现、Spring的JDBCTemplate详解
- Objective-C Method Swizzling
- 【GDOI2017第三轮模拟day2】树的难题(点剖,树状数组)
- C与C++中的const用法
- uboot的Makefile分析
- V4L2视频采集与视频编码学习目录及总结
- 克隆二叉树
- 泛型数组+泛型嵌套+泛型应用实例
- 无聊写的 一个Soeckt 客户端例子
- 贪心 【还要做题】