美文网首页
runtime方法交换

runtime方法交换

作者: 85ca4232089b | 来源:发表于2020-03-27 14:34 被阅读0次
    
    #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
    
    

    相关文章

      网友评论

          本文标题:runtime方法交换

          本文链接:https://www.haomeiwen.com/subject/wvmluhtx.html