美文网首页
消息查找

消息查找

作者: 开发狗 | 来源:发表于2020-12-17 20:03 被阅读0次
    消息查找流程简略图

    类查找

    先查找类中的方法然后再查找分类方法,分类中的方法会添加到类中的方法列表后面

    lookUpImpOrForward

    • 以下通过断点调试的方式进行查找
      当对象调用方法时会调用objc_msgSend中先进行判断在缓存中是否存在,如果不存在将会走到_objc_msgSend_uncached未缓存中查找
      objc_msgSend
      此时我们使用断点进入就可以看到,进入objc_msgSend_uncached中时调用了lookUpImpOrForward方法,全局搜索lookUpImpOrForward方法可以知道该方法是一个C++方法,可以查到具体的实现,此时我们就知道在调用objc_msgSend后主要现在该方法中进行了方法的判断处理。
      objc_msgSend

    查找思路:查找方式是什么,条件是什么,,返回什么?

    • 查找方式是什么?
      lookUpImpOrForward()
      lookUpImpOrForward方法中,首先调用一个_objc_msgForward_impcache方法,通过调试汇编进行查找可以找到 __objc_msgForward
      是在缓存中逐级进行消息转发找到一个目标进行处理,然后初始化一个临时的`imp = nil; Class = curClass;
      lookUpImpOrForward()
      lookUpImpOrForward()

    当函数调用走到该判断语句时,需要解释一个behavior参数,通过汇编可以看到参数 behavior是通过LOOLUP_INITIALIZE = 1LOOKUP_RESOLVER = 2 通过|按位或的方式进行获得,此时behavior的值为3

    1608195746783.jpg
    LOOKUP_CACHE = 4,因此此时不会进入缓存中进行快速查找,接下来是对条件的一些判断比如类的初始化等此处略过。 内存查找
    首先调用了Method meth = getMethodNoSuper_nolock(),该方法的主要作用是通过二分查找的方式在当前类的方法列表中进行二分查找,主要用到的方法如下
    getMethodNoSuper_nolock()

    因为objc_class 中的class_data_bits_t bits 中的class_rw_t data包含了类的属性方法协议,所以可以调用相关方法来获取当前类的全部实例方法。

    findMethodInSortedMethodList
    在该方法中就是通过使用指针来进行二分查找,在当前的方法列表中进行查找。

    如果查找到了,把找到的函数指针地址给到当前临时变量imp,并走到

    done:
            log_and_file_cache(cls, imp, sel, inst, curClass);
    

    通过内部的调用cache_t 中的insert方法,把当前方法插入到缓存的适当位置,至于是如何插入的,缓存是如何分配的可以查看cache_t讲解。

    如果内有找到将进行在父类中逐级查找的方式进行查找,如果最后找到根类NSObject还是没有找到,将把forward_imp赋值给imp来进行消息转发。

    消息转发前给的机会
    在这段代码中LOOKUP_RESOLVER = 2,调用resolveMethod_locked方法
    resolveMethod_locked
    然后就是在resolveInstanceMethod 方法中进行处理。
    此时我们就可以重写resolveInstanceMethod方法,在该方法中为未实现的函数进行设置目标对象和函数。如果没有进行处理将进行消息转发。

    消息转发流程

    消息转发流程

    扩展

    • 在进行二分查找时是优先在分类中查找而不是在本类中

    相关文章

      网友评论

          本文标题:消息查找

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