美文网首页
iOS 黑魔法 - Method Swizzling实现原理

iOS 黑魔法 - Method Swizzling实现原理

作者: smile_frank | 来源:发表于2021-10-13 11:51 被阅读0次

    Method Swizzling

    Method Swizzling,顾名思义,就是交换两个 方法的实现。简单来说,就是利用Objective-C Runtime的动态绑定特性,将一个方法的实现与另 一个方法的实现进行交换。

    objc_class

    在Objective-C的Runtime中,一个类是用一个名为objc_class的 结构体表示的,它的定义如下:

    objc_method_list

    我们从上述结构体中可以发现一 个objc_method_list指针,它保存着当前类的所有方法列表。同 时,objc_method_list也是一个结构体,它的定义如下:

    objc_method

    我们从上面的结构体中发现一个objc_method字段,它的定义如下:


    我们从上面的结构体中还发现,一个方法由如下三部分组成。

    • method_name:方法名。
    • method_types:方法类型。
    • method_imp:方法实现。

    交换原理

    使用Method Swizzling交换方法,其实就是修改了objc_method 结构体中的mthod_imp,即改变了method_name和method_imp的映射关系如下:


    实现Method Swizzling的相关函数

    Method class_getInstanceMethod(Class_Nullable aClass,SEL_Nonnull aSelector) OBJC_AVAILABLE(10.0,2.0,9.0,1.0,2.0);

    • 功能:返回目标类aClass、方法名为aSelector 的实例方法。
    • 参数说明
      • aClass:目标类。
      • aSelector:方法名。
        注意点只有当前类以及它的父类均不包含指定 的方法时,才会返回NULL。

    BOOL class_addMethod(Class_Nullable aClass,SEL_Nonnull aSelector,IMP_Nonnullimp,const char * _Nullable types) OBJC_AVAILABLE(10.5,2.0,9.0,1.0,2.0);

    • 功能:给目标类aClass添加一个新的方法, 同时包括方法的实现。

    • 参数说明

      • aClass:目标类。
      • aSelector:要添加方法的方法名。
      • imp:要添加方法的方法实现。
      • types:方法实现的编码类型。

    注意点 返回成功,说明已经成功在目标类中添 加了该方法;返回失败,说明在目标类中已经存 在相同方法名的方法。

    IMP method_getImplementation(Method_Nonnull method) OBJC_AVAILABLE (10.5,2.0,9.0,1.0,2.0);

    • 功能:返回方法实现的指针。

    • 参数说明

      • method:目标方法。

    IMP class_replaceMethod(Class_Nullable aClass,SEL_Nonnull aSelector,IMP_Nonnull imp,const char * _Nullable types) OBJC_AVAILABLE(10.5,2.0,9.0,1.0,2.0);

    • 功能:替换目标类aClass的aSelector方法的指 针。
    • 参数说明
      • aClass:目标类。
      • aSelector:目前方法的方法名。
      • imp:新方法的方法实现。
      • types:方法实现的编码类型。

    void method_exchangeImplementations(Method_Nonnull m1,Method_Nonnull m2) OBJC_AVAILABLE(10.5,2.0,9.0,1.0,2.0);

    • 功能:交换两个方法的实现指针。
    • 参数说明
      • m1:交换方法1。
      • m2:交换方法2
    #import <objc/runtime.h>
    
    @implementation NSObject (Swizzler)
    
    
    + (BOOL)sensorsdata_swizzleMethod:(SEL)originalSEL withMethod:(SEL)alternateSEL {
       
        //获取原始的方法
        Method originalMethod = class_getInstanceMethod(self, originalSEL);
        if (!originalMethod) {
            return NO;
        }
        //获取将要交换的方法
        Method alternateMethod = class_getInstanceMethod(self, alternateSEL);
        if (!alternateMethod) {
            return NO;
        }
        //交互两个方法的实现
        method_exchangeImplementations(originalMethod, alternateMethod);
        //返回yes,方法交换成功
        return YES;
    }
    
    @end
    
    

    相关文章

      网友评论

          本文标题:iOS 黑魔法 - Method Swizzling实现原理

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