iOS

iOS 方法交换 method_exchangeImplemen

2022-03-10  本文已影响0人  码代码的鱼

方法交换

使用方法交换需要注意些什么呢

1、在交换系统方法后要注意结束前调用本方法,也就是执行系统方法

2、再交换前,判断类中是否已经实现了系统方法,没有的话需要增加方法,避免交换父类方法

3、加dispatch_once,只执行一次

方法交换

当我们用如下方法写方法交换的时候,会出现什么问题呢

+ (void)hookClass:(Class)classObject originalSelector:(SEL)originalSelector swizzledSelector:(SEL)swizzledSelector {

    Method method1 = class_getInstanceMethod(classObject, originalSelector);

    Method method2 = class_getInstanceMethod(classObject, swizzledSelector);

    method_exchangeImplementations(method1, method2);

}

设想一种情况,想交换UIButton的sendAction方法,用上述方法,实际上交换的是父类的sendAction和UIButton的custom方法,那么当点击其他继承UIControl的类时,比如UISegmentedControl,会出现崩溃,因为调用UISegmentedControl的sendAction调用的是custom方法,但是UISegmentedControl是没有这个custom方法的,就会抛出异常

那么就要增加判断

+ (void)load{

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

        Method originalMethod = class_getInstanceMethod([self class], @selector(originalMethod));

        Method swizzlingMethod = class_getInstanceMethod([self class], @selector(swizzlingMethod));

        BOOL isAdded = class_addMethod([self class], method_getName(originalMethod), method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));

        if (isAdded)

        {

            //添加成功说明方法在原类中不存在,用下面的方法替换其实现");

            class_replaceMethod([self class], method_getName(originalMethod), method_getImplementation(swizzlingMethod), method_getTypeEncoding(swizzlingMethod));

        }

        else

        {

            NSLog(@"方法在原类中存在,用下面的方法交换其实现方法");

            method_exchangeImplementations(originalMethod, swizzlingMethod);

        }

   });

}

或者

// 这两行与以前没有任何变化

    Method originalMethod = class_getInstanceMethod(class, originalSelector);

    Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);

    //如果本类中,没有此SEL,那就会去父类里找,返回的就是父类里的信息,然后将父类的信息,添加到本类中,就相当于,本类完全的继承了父类的方法,

    BOOL didAddMethod = class_addMethod(class, originalSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));

    if (didAddMethod) {

        //添加成功说明方法在原类中不存在,添加后本类中,已经有一个originalSelector方法了

        //

        //我们重新获得一下originalMethod,(我们第一次获得originalMethod是返回父类的originalMethod,这次是本类的)

        originalMethod = class_getInstanceMethod(class, originalSelector);

    }

    method_exchangeImplementations(swizzledMethod, originalMethod);

第二种和第三种原理是一样的,只是写法略有不同

上一篇下一篇

猜你喜欢

热点阅读