美文网首页
Method swizzling

Method swizzling

作者: 韩叨叨 | 来源:发表于2018-03-15 16:08 被阅读13次

    iOS Method swizzling

    原理
    1.发生在运行时,主要用于在运行时将两个方法交换。
    2.代码可以写在任何地方,但是只有在这段交换代码执行完毕之后才起作用。
    3.也是面向AOP(面向切面编程)的一种实现方式。

    在OC语言的runtime特性中,调用一个对象的方法就是给这个对象发送消息,是通过查找接收消息对象的方法列表,从方法列表中查找对应的SEL,这个SEL对应一个IMP(一个IMP对应多个SEL),通过这个IMP找到对应的方法调用。

    在每个类中都有一个dispatch table,这个Dispatch Table本质是将类中的SEL和IMP(可以理解为函数指针)进行对应。而我们的Method Swizzling就是对这个table进行了操作,让SEL对应另一个IMP。

    使用

    +(void)load{
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            Class aclass = [self class];
            
            SEL originalSelector = @selector(printName);
            SEL swizzlingSelector = @selector(printSex);
            
            Method originalMethod = class_getInstanceMethod(aclass, originalSelector);
            Method swizzlingMethod = class_getInstanceMethod(aclass, swizzlingSelector);
            method_exchangeImplementations(originalMethod, swizzlingMethod);
        });
    }
    

    直接交换IMP是比较危险的。因为如果这个类中如果没有实现这个方法,class_getInstanceMethod()返回的是父类的method对象,这样交换的话,会把父类的原始实现(IMP)和这个类的Swizzle交换了,这样就会出现问题。

    所以如果类中没有实现 Original selector 对应的方法,那就先添加 Method,并将其 IMP 映射为 Swizzle 的实现。然后替换 Swizzle selector 的 IMP 为 Original 的实现;否则交换二者 IMP

    +(void)load{
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            Class aclass = [self class];
            
            SEL originalSelector = @selector(printName);
            SEL swizzlingSelector = @selector(printSex);
            
            Method originalMethod = class_getInstanceMethod(aclass, originalSelector);
            Method swizzlingMethod = class_getInstanceMethod(aclass, swizzlingSelector);
            
            BOOL didAddMethod = class_addMethod(aclass, originalSelector, method_getImplementation(swizzlingMethod), method_getTypeEncoding(swizzlingMethod));
            
            if (didAddMethod) {
                class_replaceMethod(aclass, swizzlingSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
            }else{
                method_exchangeImplementations(originalMethod, swizzlingMethod);
            }
            
        });
    }
    

    相关文章

      网友评论

          本文标题:Method swizzling

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