#import "UIImage+customer.h"
#import <objc/runtime.h>
@implementation UIImage (customer)
+ (void)load{
/**
* 我们在这里使用class_addMethod()函数对Method Swizzling做了一层验证,如果self没有实现被交换的方法,会导致失败。
* 而且self没有交换的方法实现,但是父类有这个方法,这样就会调用父类的方法,结果就不是我们想要的结果了。
* 所以我们在这里通过class_addMethod()的验证,如果self实现了这个方法,class_addMethod()函数将会返回NO,我们就可以对其进行交换了。
*/
Class class2 = object_getClass(self);
/**
* 对象方法是依实例方法的形式存在类当中的。 [self class]
* 类方法是依实例方法的形式存在元类当中的 class2
*/
[self hookClass:class2 originalSelector:@selector(swizzlingImageName:) swizzledSelector:@selector(imageNamed:)];
[self hookClass:[self class] originalSelector:@selector(swizzlingInitWithData:) swizzledSelector:@selector(initWithData:)];
}
+ (void)hookClass:(Class)classObject originalSelector:(SEL)originalSelector swizzledSelector:(SEL)swizzledSelector {
Class class = classObject;
//第三版Hook核心思想是,
//如果本类中有 originalSelector 方法,直接交换。
//如果本类中没有 originalSelector 方法,添加父类的的方法到子类,然后再直接交换。
// 这两行与以前没有任何变化
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
//class_addMethod 添加的SEL是 originalSelector ,IMP 是 method_getImplementation(originalMethod),我称他们为原配,
//如果本类中,已经有 originalSelector,再添加 originalSelector, 肯定返回NO,添加失败,那就直接交换了,跟第一版hook流程一模一样了,
//如果本类中,没有此SEL,那就会去父类里找,返回的就是父类里的信息,然后将父类的信息,添加到本类中,就相当于,本类完全的继承了父类的方法,
BOOL didAddMethod = class_addMethod(class, originalSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
if (didAddMethod) {
//添加成功后,本类中,已经有一个originalSelector方法了
//我们第一次获得originalMethod是返回父类的originalMethod
//我们需要再重新获得一下originalMethod,这次返回的不是父类的originalMethod
//而是我们刚刚class_addMethod添加的到本类的originalMethod
originalMethod = class_getInstanceMethod(class, originalSelector);
}
//走到这,就证明了,本类中肯定已经有这两个方法了,那就这样直接交换吧。
method_exchangeImplementations(swizzledMethod, originalMethod);
}
+ (instancetype)swizzlingImageName:(NSString*)name{
name = [NSString stringWithFormat:@"test_1"];
return [self swizzlingImageName:name];
}
- (instancetype)swizzlingInitWithData:(NSData*)data{
NSLog(@"===========");
return [self swizzlingInitWithData:data];
}
@end
网友评论