美文网首页
iOS - Runtime Swizzling 源码剖析

iOS - Runtime Swizzling 源码剖析

作者: 码代码的小马 | 来源:发表于2021-05-14 10:01 被阅读0次

Runtime源码下载
源码位于objc-class-old.m

void method_exchangeImplementations(Method m1_gen, Method m2_gen)
{
    IMP m1_imp;
    old_method *m1 = oldmethod(m1_gen);
    old_method *m2 = oldmethod(m2_gen);
    if (!m1  ||  !m2) return;

    impLock.lock();
    m1_imp = m1->method_imp;
    m1->method_imp = m2->method_imp;
    m2->method_imp = m1_imp;
    impLock.unlock();
}

objc-runtime-new.m

void method_exchangeImplementations(Method m1, Method m2)
{
    if (!m1  ||  !m2) return;

    mutex_locker_t lock(runtimeLock);

    IMP imp1 = m1->imp(false);
    IMP imp2 = m2->imp(false);
    SEL sel1 = m1->name();
    SEL sel2 = m2->name();

    m1->setImp(imp2);
    m2->setImp(imp1);


    // RR/AWZ updates are slow because class is unknown
    // Cache updates are slow because class is unknown
    // fixme build list of classes whose Methods are known externally?

    flushCaches(nil, __func__, [sel1, sel2, imp1, imp2](Class c){
        return c->cache.shouldFlush(sel1, imp1) || c->cache.shouldFlush(sel2, imp2);
    });

    adjustCustomFlagsForMethodChange(nil, m1);
    adjustCustomFlagsForMethodChange(nil, m2);
}
    IMP imp(bool needsLock) const {
        if (isSmall()) {
            IMP imp = remappedImp(needsLock);
            if (!imp)
                imp = ptrauth_sign_unauthenticated(small().imp.get(),
                                                   ptrauth_key_function_pointer, 0);
            return imp;
        }
        return big().imp;
    }
    void setImp(IMP imp) {
        if (isSmall()) {
            remapImp(imp);
        } else {
            big().imp = imp;
        }
    }

从源码来看,底层直接交换了SEL的 IMP

相关文章

网友评论

      本文标题:iOS - Runtime Swizzling 源码剖析

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