重学 ObjC 消息机制

栏目: Objective-C · 发布时间: 5年前

内容简介:消息机制是 Objective-C 语言的基础,也是它动态化的核心所在。笔者在阅读 objc 源码之后,对该语言的使用有了一些新的思考。对象或者类在响应消息时,最多会经历 5 个过程:消息的响应过程其实是根据选择子(sel)查找对应的函数实现(imp)的过程。

消息机制是 Objective-C 语言的基础,也是它动态化的核心所在。笔者在阅读 objc 源码之后,对该语言的使用有了一些新的思考。

对象或者类在响应消息时,最多会经历 5 个过程:

  1. 查找当前类的缓存
  2. 在当前类的方法列表查找
  3. 在父类缓存及方法列表查找
  4. 消息决议
  5. 消息转发

消息的响应过程其实是根据选择子(sel)查找对应的函数实现(imp)的过程。

查找当前类的缓存

发送消息的 objc_msgSend 函数会通过 cache_getImp 函数查找缓存,因为所有方法的执行,都会调用这两个函数,为了提高性能,这两个函数由汇编实现。

如果方法缓存没有命中,会在当前类的 methods 中查找。

查找当前类的方法列表

当前类的方法列表底层是一个二维指针数组,存储当前类以及所有 category 的方法。二维的方法列表是在 runtime 初始化的时候构建的,先添加主类的方法列表,然后依次添加 category 的,后添加的列表会放在数组的前面。

在查找时,会依次遍历二维数组中的每个元素列表,然后在列表中使用二分查找,直到找到选择子(sel)对应的方法实现(imp)才终止。找到后使用 log_and_fill_cache 写入当前类的缓存。

如果这个过程没有找到,会进入父类查找。

在父类缓存及方法列表查找

在查找父类的方法列表前,会先查找父类的方法缓存,如果缓存没有命中才会遍历方法列表查找。查找过程和在当前类相似。

如果在父类中找到对应的实现,会将该方法缓存到 当前类 中。

如果直到 NSObject 都没有找到方法对应的实现,会进入方法决议。

方法决议

方法的决议分为实例方法和类方法,因为两者的过程都相似,所以这里只讲实例方法。

方法决议时会触发 resolveInstanceMethod: 方法的调用,如果当前类实现该方法,并在该方法中使用 class_addMethod() 动态的为参数 sel 关联实现(imp),那么在返回 YES 后会调用新关联的 imp ,并缓存。

如果在方法决议时,没有动态的关联实现,便会触发消息转发。

消息转发

消息的转发有两种形式 forwardingTargetForSelectorforwardInvocation 功能有所差别。

forwardingTargetForSelector: 需要返回一个能够响应 sel 消息的对象。如果该对象无法响应传入的选择子会调用 forwardInvocation:

forwardInvocation: 调用前需要通过 methodSignatureForSelector: 方法提供方法签名。

forwardInvocation: 接受一个 NSInvocation 参数,该对象包含当前选择子和对象。然而我们完全可以忽视这个参数做任何事情,因为只要这个方法实现,当前对象就不会再抛无法响应消息的异常了。

所以需要谨慎的重载这个方法,否者如果某个未知方法没有实现,却不会抛出异常,就无法察觉了。

最后如果没有实现消息转发,会在根类 NSObject 中调用 doesNotRecognizedSelector 抛异常。

总结

从响应消息的流程上来看,存在一些值得思考的地方。

应该尽量减少 Category 的数量,因为 Category 会作为元素添加到二维指针数组,增加数组的长度,也就增加方法查找的时间消耗。

Category 的方法会先于主类被查找到,如果 Category 使用了主类的同名方法,主类的实现会被覆盖。

在方法决议时,会使用 class_addMethod 动态添加方法的实现,该方法会将新加的方法作为一个单一的 list 元素,添加到二维指针数组,同样会增加数组的长度。

同时,该函数在添加新方法后会冲刷(flush)方法缓存。其目的是为了防止先前存在同名的方法被调用过,被缓存,再次调用会命中缓存,而不会执行新添加的方法实现。

消息转发其实是变相的实现了多态,将当前类的消息交给其他类处理,甚至忽略转发的消息而去做其他事情。

不过,到达消息转发需要经历前面的四步,也是一笔不小的开销,过多的依赖转发来响应消息会影响性能。

参考:

从源代码看 ObjC 中消息的发送

objc 源码


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

C标准库

C标准库

P. J. Plauger / 卢红星、徐明亮、霍建同 / 人民邮电出版社 / 2009-7 / 79.00元

本书是由世界级C语言专家编写的C标准库经典著作。英文版已经重印十多次,影响了几代程序员。 本书结合C标准的相关部分,精辟地讲述了每一个库函数的使用方法和实现细节,而这正是一个真正的C程序员所必须掌握的。更重要的是,书中给出了实现和测试这些函数的完整源代码,可以让你更深入地学习C语言。不仅如此,本书还讨论了一些即使是最有经验的C程序员通常也不熟悉的知识,比如国际化和独立于区域设置的程序的编写、......一起来看看 《C标准库》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试