美文网首页iOS进阶
iOS 消息查找流程

iOS 消息查找流程

作者: Joker_King | 来源:发表于2019-12-31 22:40 被阅读0次

在上次的objc_msgSend分析的文章中,我们得知,方法的本质就是调用objc_msgSend函数来发送消息。

接下来我们通过在代码中打断点来跟进一下这个流程。



我们将断点的显示模式改为汇编显示。


然后将代码运行起来。


我们可以很清楚的看到,对象在调用方法时,底层是通过调用objc_msgSend函数来发送消息的,我们在objc_msgSend函数处打上断点,继续跟进去看看。

我们可以清楚的看到,objc_msgSend在缓存没有命中之后调用了_objc_msgSend_uncached

_objc_msgSend_uncached

_objc_msgSend_uncached调用了_class_lookupMethodAndLoadCache3

_class_lookupMethodAndLoadCache3

通过上面的图片,我们可以清楚的看到_class_lookupMethodAndLoadCache3函数是存在于objc-runtime-new.mm:4845这个文件中。接下来我们来看看这个函数中都做了些什么。

IMP _class_lookupMethodAndLoadCache3(id obj, SEL sel, Class cls)
{
    return lookUpImpOrForward(cls, sel, obj, 
                              YES/*initialize*/, NO/*cache*/, YES/*resolver*/);
}

lookUpImpOrForward

  • 在类对象的方法列表中查找IMP。
    {
        Method meth = getMethodNoSuper_nolock(cls, sel);
        if (meth) {
            log_and_fill_cache(cls, meth->imp, sel, inst, cls);
            imp = meth->imp;
            goto done;
        }
    }
  • 如果没找到,继续在父类的缓存的方法列表中查找IMP。
{
        unsigned attempts = unreasonableClassCount();
        for (Class curClass = cls->superclass;
             curClass != nil;
             curClass = curClass->superclass)
        {
            // Halt if there is a cycle in the superclass chain.
            if (--attempts == 0) {
                _objc_fatal("Memory corruption in class list.");
            }
            
            // Superclass cache.
            imp = cache_getImp(curClass, sel);
            if (imp) {
                if (imp != (IMP)_objc_msgForward_impcache) {
                    // Found the method in a superclass. Cache it in this class.
                    log_and_fill_cache(cls, imp, sel, inst, curClass);
                    goto done;
                }
                else {
                    // Found a forward:: entry in a superclass.
                    // Stop searching, but don't cache yet; call method 
                    // resolver for this class first.
                    break;
                }
            }
            
            // Superclass method list.
            Method meth = getMethodNoSuper_nolock(curClass, sel);
            if (meth) {
                log_and_fill_cache(cls, meth->imp, sel, inst, curClass);
                imp = meth->imp;
                goto done;
            }
        }
    }
  • 如果IMP没有找到,则尝试做一次动态方法解析。
    if (resolver  &&  !triedResolver) {
        runtimeLock.unlock();
        _class_resolveMethod(cls, sel, inst);//这里做一次动态方法解析。
        runtimeLock.lock();
        // Don't cache the result; we don't hold the lock so it may have 
        // changed already. Re-do the search from scratch instead.
        triedResolver = YES;
        goto retry;
    }
  • 如果没有找到IMP,并且方法解析也没有处理,那么则进入消息转发流程。
// No implementation found, and method resolver didn't help. 
    // Use forwarding.

    imp = (IMP)_objc_msgForward_impcache;

至此,关于方法查找流程的分析就结束了,下一章,我们来分析方法的转发流程。

相关文章

  • iOS 消息查找流程

    在上次的objc_msgSend分析的文章中,我们得知,方法的本质就是调用objc_msgSend函数来发送消息。...

  • iOS 消息转发机制

    上节(iOS 消息查找流程)我们讲到,在iOS中对象调用方法,会经历方法的查找,如果查找到方法的IMP,那么就返回...

  • ios 消息查找流程-慢速查找

    上篇文章ios objc_msgSend分析也就是消息查找的快速流程,这篇文章我们就来分析一下消息查找的慢速流程。...

  • iOS底层 消息查找流程

    接上篇iOS底层 objc_msgSend分析消息发送会调用lookUpImpOrForward方法,源码如下, ...

  • iOS 底层原理 - 消息转发

    在上一篇 iOS 底层原理 - 消息查找流程中,我们知道OC消息机制分为三个阶段,消息发送,动态解析和消息转发,如...

  • iOS 底层原理 - 消息查找流程

    我们从之前的方法的本质objc_msgSend分析一篇中得知了解到objc_msgSend发送消息进入到了汇编,找...

  • iOS 消息发送查找&转发流程

    objc源码下载地址通过断点结合C++源码调试流程汇编部分 OC中调用方法其实就是给类发送消息objc_msgSe...

  • 消息查找流程

    上节我们分析了objc_msgSend的快速查找部分(汇编部分),这一节我们来分析其慢速部分,也就是c语言部分。 ...

  • 消息查找流程

    iOS中方法的查找分为两部分: 快速查找,在缓存中直接找到发送的消息 慢速查找,在缓存中如果没找到就到了慢速查找,...

  • iOS底层系列14 -- 消息流程的动态方法决议与转发

    在iOS底层系列12 -- 消息流程的快速查找[https://www.jianshu.com/p/ee58348...

网友评论

    本文标题:iOS 消息查找流程

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