method swizzling
不想再多说什么了。
但是网上对于此的讲述大都是文绉绉、理解起来不是那么随性…特此稍微记一下,方便大家理解。代码贴一下,好参照对比一下。
#import "UIImage+hook.h"
#import <objc/runtime.h>
@implementation UIImage (hook)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class selfClass = object_getClass([self class]);
SEL oriSEL = @selector(imageNamed:);
Method oriMethod = class_getInstanceMethod(selfClass, oriSEL);
SEL cusSEL = @selector(myImageNamed:);
Method cusMethod = class_getInstanceMethod(selfClass, cusSEL);
BOOL addSucc = class_addMethod(selfClass, oriSEL, method_getImplementation(cusMethod), method_getTypeEncoding(cusMethod));
if (addSucc) {
class_replaceMethod(selfClass, cusSEL, method_getImplementation(oriMethod), method_getTypeEncoding(oriMethod));
}else {
method_exchangeImplementations(oriMethod, cusMethod);
}
});
}
+ (UIImage *)myImageNamed:(NSString *)name {
NSString * newName = [NSString stringWithFormat:@"%@%@", @"new_", name];
return [self myImageNamed:newName];
}
@end
Method class_getClassMethod(Class cls , SEL name) //是获取某个类的类方法。 Method class_getInstanceMethod(Class cls , SEL name) //是获取某个类的实例方法。
BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types) //SEL : 类成员方法的指针,但不同于C语言中的函数指针,函数指针直接保存了方法的地址,但SEL只是方法编号。 //IMP:一个函数指针,保存了方法的地址。
【For example 】
比方我有一只狗,不知道能不能吃、不知道能不能游泳。(就是那么愚蠢…)
但是我突发奇想,让他吃的时候,他就去游泳。
Step1:
首先我让他吃的时候直接执行游泳的实现。
BOOL addSucc = class_addMethod(selfClass, oriSEL, method_getImplementation(cusMethod), method_getTypeEncoding(cusMethod));
(1)如果成功了。那么这确实是个玩具狗。
本身不会吃,我给了吃的buff。并且让它吃的指令,它就去游泳…
那么把它的游泳改成吃就OK这里写代码片
了。
class_replaceMethod(selfClass, cusSEL, method_getImplementation(oriMethod), method_getTypeEncoding(oriMethod));
(2)如果失败了。说明这是个真狗。以前就可以吃,再添加吃的实现失败。
我只需要交换下吃和游泳的imp。吃 <==> 游泳
method_exchangeImplementations(oriMethod, cusMethod);
当然了,游泳这个方法有啥操作就不那么重要了。可以让它真去游泳,也可以无操作…
Ps:刚才脑袋短路,竟然想为啥用 class_replaceMethod
不用method_exchangeImplementations
….
截止到刚才。吃 -> 游泳 如果我用method_exchangeImplementations
,不就又把吃 -> 吃了吗…
希望可以帮助大家更加幽默的理解Method Swizzling
…