美文网首页
objc_msgSend流程分析:动态方法决议和消息转发

objc_msgSend流程分析:动态方法决议和消息转发

作者: CrazySnow | 来源:发表于2020-09-28 16:06 被阅读0次

    动态方法决议

    紧接着上文的快速查找、慢速查找之后,如果还没找到方法,则根据apple提供的建议

    • 进行一次动态方法决议
    • 如果还没找到,则进行消息转发(快速转发、慢速转发)

    动态方法决议:Objective C 提供了一种名为动态方法决议的手段,使得我们可以在运行时动态地为一个selector 提供实现。我们只要实现 +resolveInstanceMethod:+resolveClassMethod: 方法,并在其中为指定的selector 提供实现即可(通过调用运行时函数class_addMethod来添加)。

    方法解析流程.pic.jpg
    static NEVER_INLINE IMP
    resolveMethod_locked(id inst, SEL sel, Class cls, int behavior)
    {
        runtimeLock.assertLocked();
        ASSERT(cls->isRealized());
    
        runtimeLock.unlock();
        //对象 -- 类
        if (! cls->isMetaClass()) { //类不是元类,调用对象的解析方法
            // try [cls resolveInstanceMethod:sel]
            resolveInstanceMethod(inst, sel, cls);
        } 
        else {//如果是元类,调用类的解析方法, 类 -- 元类
            // try [nonMetaClass resolveClassMethod:sel]
            // and [cls resolveInstanceMethod:sel]
            resolveClassMethod(inst, sel, cls);
            //为什么要有这行代码? -- 类方法在元类中是对象方法,所以还是需要查询元类中对象方法的动态方法决议
            if (!lookUpImpOrNil(inst, sel, cls)) { //如果没有找到或者为空,在元类的对象方法解析方法中查找
                resolveInstanceMethod(inst, sel, cls);
            }
        }
    
        // chances are that calling the resolver have populated the cache
        // so attempt using it
        //如果方法解析中将其实现指向其他方法,则继续走方法查找流程
        return lookUpImpOrForward(inst, sel, cls, behavior | LOOKUP_CACHE);
    }
    
    • 判断类是否是元类
      • 如果是类,执行实例方法的动态方法决议resolveInstanceMethod
      • 如果是元类,执行类方法的动态方法决议resolveClassMethod,如果在元类中没有找到或者为空,则在元类的实例方法的动态方法决议resolveInstanceMethod中查找,主要是因为类方法在元类中是实例方法,所以还需要查找元类中实例方法的动态方法决议
    • 如果动态方法决议中,将其实现指向了其他方法,则继续查找指定的imp,即继续慢速查找lookUpImpOrForward

    消息转发流程

    如果在经历了快速查找、慢速查找、动态方法决议后,仍没有找到方法的实现,就会进行消息转发,消息转发分为:

    • 快速转发:forwardingTargetForSelector
    • 慢速转发:methodSignatureForSelectorforwardInvocation

    消息转发的处理主要分为两部分:

    【快速转发】当慢速查找,以及动态方法决议均没有找到实现时,进行消息转发,首先是进行快速消息转发,即走到forwardingTargetForSelector方法
    如果返回消息接收者,在消息接收者中还是没有找到,则进入另一个方法的查找流程

    如果返回nil,则进入慢速消息转发

    【慢速转发】执行到methodSignatureForSelector方法
    如果返回的方法签名为nil,则直接崩溃报错

    如果返回的方法签名不为nil,走到forwardInvocation方法中,对invocation事务进行处理,如果不处理也不会报错

    消息转发流程(转自Style_月月).png

    objc_msgSend发送消息的流程描述

    【快速查找流程】首先,在类的缓存cache中查找指定方法的实现

    【慢速查找流程】如果缓存中没有找到,则在类的方法列表中查找,如果还是没找到,则去父类链的缓存和方法列表中查找

    【动态方法决议】如果慢速查找还是没有找到时,第一次补救机会就是尝试一次动态方法决议,即重写resolveInstanceMethod/resolveClassMethod方法

    【消息转发】如果动态方法决议还是没有找到,则进行消息转发,消息转发中有两次补救机会:快速转发+慢速转发

    如果转发之后也没有,则程序直接报错崩溃unrecognized selector sent to instance

    相关文章

      网友评论

          本文标题:objc_msgSend流程分析:动态方法决议和消息转发

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