美文网首页
底层12:Runtime-消息机制

底层12:Runtime-消息机制

作者: 张无奈 | 来源:发表于2020-09-02 00:04 被阅读0次

面试题:讲一下OC的消息机制。

OC中的方法调用其实都是转成了objc_msgSend函数的调用,给receiver(方法调用者)发送了一条消息(selector方法名)。objc_msgSend底层有3大阶段:

消息发送(当前类、父类中直接找)、动态方法解析、消息转发。

消息发送:

1.判断消息接受者是否为nil,为nil就退出;

2.不为nil就通过isa指针找到接受者的类对象,查找里面缓存的方法是否有该消息,

       1)有就调用方法、结束查找。

        2)没有就从rw_t方法列表中查找,

              1>.有就调用方法、结束查找、并将方法缓存到该接收者的缓存列表中;

              2>.没有就通过superClass指针找到父类,再从父类的缓存列表中查找;

                  a. 找到就调用方法、结束查找并将方法缓存到该接收者的缓存列表中;

                  b.没有就从该父类的方法列表中查找;

                        + 有就调用方法、结束查找并将方法缓存到该接收者的缓存列表中,

                        + 没有就继续通过superClass指针继续查找...;

动态方法解析:

最后整个体系都没有就会进入动态方法解析过程,首先判断是否曾经有过动态解析:

没有的话,调用+resolveInstanceMethod或者+resolveClassMethod:方法来动态解析,

并标记为已经动态解析,然后进入消息发送重复上面的过程,最后到曾经有过动态解析直接转入消息转发。

消息转发:

进入消息转发会调用forwardingTargetForSelector:方法。

返回值不为nil,就会调用objc_msgSend(返回值,SEL);

返回值为nil,调用methodSignatureForSelector:方法:

          返回为nil,直接报错方法找不到,调用doesNotRecognizeSelector:方法;

          返回不为nil,调用forwardInvocation方法

面试题:消息转发机制流程?

首先会去实现forwardingTargetForSelector:方法。

1).如果让该方法去执行,即返回值不为nil,就会调用objc_msgSend(返回值,SEL);

2).返回值为nil,调用methodSignatureForSelector:方法。

       a.如果该方法返回为nil,直接报错方法找不到,调用doesNotRecognizeSelector:方法;

       b.返回不为nil,调用forwardInvocation方法,开发者可以在该方法中自定义任何逻辑。



OC中的方法调用,其实都是转换为objc_msgSend函数的调用。

objc_msgSend(对象,@selector(方法))

objc_msgSend如果找不到合适的方法调用,会报错unrecognized selector send to instance

OC的方法调用:消息机制,给方法调用者发送消息。

objc_msgSend的执行流程可以分为3大阶段

消息发送

给方法调用者发送消息,尝试找到方法。找到不会往下进行,否则进行动态方法解析。

动态方法解析

在消息发送阶段没有找到对应的方法,会进入动态方法解析,先判断是否曾经有过动态解析,没有的话,调用+resolveInstanceMethod或者resolveClassMethod:方法来动态解析,并标记为已经动态解析,然后进入消息发送;如果曾经有过动态解析,直接转入消息转发。  

添加实例方法

添加类方法

消息转发:将消息转发给别人

调用forwardingTargetForSelector:方法。返回值不为nil,就会调用objc_msgSend(返回值,SEL);

返回值为nil,调用methodSignatureForSelector:方法。返回为nil,直接报错方法找不到,调用doesNotRecognizeSelector:方法;返回不为nil,调用forwardInvocation方法

能来到forwardInvocation:方法,可以尽情的做你想做的(可以不写,或者打印)。而如上所写相当于把消息转发给MJCat,完全可以在forwardTargetForSelector:方法中实现。

上面是调用实力方法时出现的消息转发过程,调用类方法不存在时新消息转发过程代码如下:

+ (id)forwardingTargetForSelector

@dynamic :提醒编译器不要自动生成setter,getter方法的实现,不要自动生成成员变量。

意味着需要去实现resolveInstanceMethod:方法

@synthesize:提醒编译器生成setter,getter方法,跟@dynamic 相反。(只是后来的Xcode默认就是要生成setter,getter方法,所以也就不需要写了)

相关文章

  • 底层12:Runtime-消息机制

    面试题:讲一下OC的消息机制。 OC中的方法调用其实都是转成了objc_msgSend函数的调用,给receive...

  • Runtime(消息转发机制)

    1、什么是Runtime Runtime->运行时机制,最主要的是消息机制,是一套比较底层的纯C语言API,属于一...

  • 底层技术以及runtime分享

    https://minilv.github.io/2019/03/17/Runtime-消息机制土味讲解/?nsu...

  • Runtime-消息机制

    Objective-C是一门动态语言,类型的判断、类的成员变量、方法的内存地址都是在程序的运行阶段才最终确定,并且...

  • runtime-消息机制

    从异常说起 我们都知道,在iOS中存在这么一个通用类类型id,它可以用来表示任何对象的类型 —— 这意味着我们使用...

  • runtime-消息机制

    OC方法调用,其实都是转换为objc_msgSend函数调用objc_msgSend的执行流程可以分为3大阶段:消...

  • Runtime-原理

    runtime初探对象与方法的本质runtime-消息发送runtime-动态方法解析runtime-消息转发 r...

  • Runtime-(三)消息传递机制

    我们知道在OC中,所有的方法调用最终都会转换成objc_msgSend形式的方法调用。如下图: 而对于调用父类的方...

  • Android的消息机制和源码分析

    消息机制概述 Android的消息机制主要是Handler的消息机制,Handler的运行需要底层的Message...

  • Android 消息机制

    Android 消息机制 android消息机制主要是Handler运行机制,其底层主要是MessageQueue...

网友评论

      本文标题:底层12:Runtime-消息机制

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