前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >iOS RunTime之三:消息发送

iOS RunTime之三:消息发送

作者头像
s_在路上
发布2018-09-11 17:09:54
5210
发布2018-09-11 17:09:54
举报
文章被收录于专栏:iOS 开发杂谈

由上面一章中,我们了解了什么是RunTime的数据结构,下面了解一下Runtime的消息发送。

我们知道[object doSomething]被编译器转化为:

代码语言:javascript
复制
id objc_msgSend ( id self, SEL op, ... );

Objective-C中,消息直到运行时才会绑定到方法的实现上。编译器会把代码中[object doSomething]转换成objc_msgSend消息函数,这个函数完成了动态绑定的所有事情,它的运行流程如下:

  • 检查selector是否需要忽略。
  • 检查target是否为nil。如果为nil,直接cleanup,然后return。(这就是我们可以向nil发送消息的原因。)
  • 然后在targetClass中根据Selector去找IMP

寻找IMP的过程:

  • 先从当前classcache方法列表(cache methodLists)里去找。
  • 如果找到了,跳到对应函数实现。
  • 如果没找到,就从class的方法列表(methodLists)里找。
  • 如果还找不到,就到super class的方法列表里找,直到找到基类(NSObject)为止。
  • 最后再找不到,就会进入动态方法解析和消息转发的机制。

Paste_Image.png

注意:

  • 这里说的分发表其实就是Class中的方法列表,它将方法选择器和方法实现地质联系起来。
  • 消息的发送其实就是先确定object接受者对象,然后根据isa指针查找其方法然后跳转过去并执行。
  • 但是编译期间,是无法确定object接受者对象。只有在程序运行期间,object接受者对象才能得到确定。这种在运行期间才确定object接受者对象,Objective-C称为动态绑定。
  • 消息发送这种工作机制明显区别另一著名面向对象编程语言——C++或者JavaC++或者Java调用对象的函数,函数与对象之间的关系,在编译期间就必须严格确定。比如Car这个对象里面没有定义函数名为fly的函数,编译器不会通过,而是会报错。Objective-C如果向Car这个对象发送字符串为flyselector,即使car没有实现fly方法,编译器依然能够通过,但是运行期间则会因为获取不到实际执行的方法而抛出异常。
  • 消息发送的设计使得编译期间Objective-C非常包容对象所属的类。在Objective-C语言中你可以向任何包括空指针nil在内的对象发你想发的消息。
  • 消息发送的机制使得在不重新编译的情况下,在运行期间,干预或者说hook原来的target(方法、变量等)变得更易于实现,更有实际应用价值,这个是需要依赖于消息发送和动态绑定的实现机制——Runtime
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016.09.20 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档