# objc_msgSend之方法查找

86 阅读2分钟

Object-C动态性

说到Objcet-C的动态性,我们可以从两点来聊。首先是类的结构的动态性,静态语音类的结构确定是在编译时候,而Objcet-C从编译推迟到了运行时。另一方面就不得不提到消息发送机制了,Objcet-C中大多数函数的调用都是通过objc_msgSend来调用的。那么本文就消息解读objc_msgSend过程中最重要的一步--方法查找。

在cache中快速查找

objc4中搜索 _objc_msgSend

image.png 可以看到各个架构版本的objc_msgSend的源码。我们主要以arm64为主,所有直接看objc_msg_arm64中的源码,可以看到都是汇编代码。这里我们可以思考一个问题,苹果为什么objc_msgSend这部分代码要使用汇编来编写呢?答案很简单--效率。汇编的效率是比c/c++更快的,因为汇编大多是直接对寄存器的读写,相比较对内存的操作更底层,效率也更高(个人愚见,欢迎评论区互喷)。另外苹果在所有的汇编方法命值钱都会用下划线开头,目的是为了防止符号冲突。

总结

之前忘了再哪收藏了一个不错的流程图,对这一过程总结的十分到位。

ba660f99997d4d09ac8a098d851ff0fd~tplv-k3u1fbpfcp-jj-mark-3024-0-0-0-q75.awebp.webp

消息转发:

8569e0b9670d481084360b97fbae0978~tplv-k3u1fbpfcp-jj-mark-3024-0-0-0-q75.awebp.webp

在消息发送的时候,如果在cache方法列表中都没有找到方法实现,会来到动态解析阶段,通过调用resolveInstanseMethodresolveClassMethod,来动态的解析方法的实现。如果在方法里返回NO,则会进入消息转发阶段,通过frowardingTargetSelector,可以将消息转发到能处理消息的实例里面。如果没有进行快速转发,可以methodSignatureForSeletorfrowardInvocation 来进行完全消息转发。

那么问题来了,苹果为什么要设计这些阶段,难到真的是怕开发者忘实现方法吗?

首先,确实动态解析,快速转发和完全转发都能做到防止程序unrecognized selector sent to instance 类型的crash,这三种方式也被称做消息发送的三根救命稻草。。这些阶段的前提都是在没有找到方法实现,设计这些并不会影响消息发送的效率。而每根稻草实际的实现原理是不同的,动态解析是动态的去添加方法实现,消息转发是让一个替代者来实现。