美文网首页iOS
iOS 方法交换 method_exchangeImplemen

iOS 方法交换 method_exchangeImplemen

作者: 码代码的鱼 | 来源:发表于2022-03-10 15:03 被阅读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);

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

    相关文章

      网友评论

        本文标题:iOS 方法交换 method_exchangeImplemen

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