Method swizzling

本文深入解析了iOS中Method Swizzling的工作原理及其应用场景,介绍了如何利用runtime特性来实现方法交换,以及在面向切面编程中的具体实现方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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);
        }

    });
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值