美文网首页
swift与oc方法查找比较

swift与oc方法查找比较

作者: 不拘小节123456 | 来源:发表于2021-10-01 09:59 被阅读0次

    对于oc的方法查找大家比较熟悉了,所有的方法调用都会走objc_msgSend
    该api必须两个参数,receiver和SEL,receiver就是该对象的isa指针,然后先在cache里面查找,如果没找到再去methodLists里面查找,如果还没有就去superclass里面找进行递归操作,都找不到就会进行消息转发操作
    下面是老版的runtime,但是逻辑类似,好理解

    struct objc_class : objc_object {
        Class superclass;
        const char *name;
        uint32_t version;
        uint32_t info;
        uint32_t instance_size;
        struct old_ivar_list *ivars;
        struct old_method_list **methodLists;
        Cache cache;
        struct old_protocol_list *protocols;
        // CLS_EXT only
        const uint8_t *ivar_layout;
    }
    //  方法的定义
    typedef struct objc_method *Method;
    struct objc_method {
        SEL method_name                                          OBJC2_UNAVAILABLE;
        char *method_types                                       OBJC2_UNAVAILABLE;
        IMP method_imp                                           OBJC2_UNAVAILABLE;
    }
    

    对于swift,它分为三种派发方式:静态派发,动态派发和消息派发(就是oc里面的派发方式)
    静态派发是最快的.我理解就是在编译的时候已经确定了函数地址进行直接调用,具体api如:static 修饰func,extension包含的func
    动态派发:他引入了v-table表的概念,从swift源码看v-table表在编译的时候回存储在metal对象里面,调用查找方式类似消息发送查找,不同的是他的查找相对淳朴,直接采用指针偏移点方式查找,由于编译时已经确定v-table表,不需要消息发送那么复杂的缓存查找方式

    可以通过SIL命令来查看当前类的v-table表
    swiftc -emit-sil main.swift
    
    void *
    swift::swift_lookUpClassMethod(const ClassMetadata *metadata,
                                   const MethodDescriptor *method,
                                   const ClassDescriptor *description) {
      assert(metadata->isTypeMetadata());
    
      assert(isAncestorOf(metadata, description));
    
      auto *vtable = description->getVTableDescriptor();
      assert(vtable != nullptr);
    
      auto methods = description->getMethodDescriptors();
      unsigned index = method - methods.data();
      assert(index < methods.size());
    // 根据方法描述取得该方法在vtable中的地址偏移
      auto vtableOffset = vtable->getVTableOffset(description) + index;
    // 本身类的起始地址
      auto *words = reinterpret_cast<void * const *>(metadata);
    // 得到动态方法的当前实际地址
      return *(words + vtableOffset);
    }
    

    参考
    https://www.jianshu.com/p/985bef8dfd30
    https://www.jianshu.com/p/ea01fe230b03
    https://www.jianshu.com/p/a4ca25caa6c9

    相关文章

      网友评论

          本文标题:swift与oc方法查找比较

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