重学 ObjC 消息机制
栏目: Objective-C · 发布时间: 5年前
内容简介:消息机制是 Objective-C 语言的基础,也是它动态化的核心所在。笔者在阅读 objc 源码之后,对该语言的使用有了一些新的思考。对象或者类在响应消息时,最多会经历 5 个过程:消息的响应过程其实是根据选择子(sel)查找对应的函数实现(imp)的过程。
消息机制是 Objective-C 语言的基础,也是它动态化的核心所在。笔者在阅读 objc 源码之后,对该语言的使用有了一些新的思考。
对象或者类在响应消息时,最多会经历 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
,并缓存。
如果在方法决议时,没有动态的关联实现,便会触发消息转发。
消息转发
消息的转发有两种形式 forwardingTargetForSelector
和 forwardInvocation
功能有所差别。
forwardingTargetForSelector:
需要返回一个能够响应 sel
消息的对象。如果该对象无法响应传入的选择子会调用 forwardInvocation:
。
在 forwardInvocation:
调用前需要通过 methodSignatureForSelector:
方法提供方法签名。
forwardInvocation:
接受一个 NSInvocation
参数,该对象包含当前选择子和对象。然而我们完全可以忽视这个参数做任何事情,因为只要这个方法实现,当前对象就不会再抛无法响应消息的异常了。
所以需要谨慎的重载这个方法,否者如果某个未知方法没有实现,却不会抛出异常,就无法察觉了。
最后如果没有实现消息转发,会在根类 NSObject
中调用 doesNotRecognizedSelector
抛异常。
总结
从响应消息的流程上来看,存在一些值得思考的地方。
应该尽量减少 Category 的数量,因为 Category 会作为元素添加到二维指针数组,增加数组的长度,也就增加方法查找的时间消耗。
Category 的方法会先于主类被查找到,如果 Category 使用了主类的同名方法,主类的实现会被覆盖。
在方法决议时,会使用 class_addMethod
动态添加方法的实现,该方法会将新加的方法作为一个单一的 list 元素,添加到二维指针数组,同样会增加数组的长度。
同时,该函数在添加新方法后会冲刷(flush)方法缓存。其目的是为了防止先前存在同名的方法被调用过,被缓存,再次调用会命中缓存,而不会执行新添加的方法实现。
消息转发其实是变相的实现了多态,将当前类的消息交给其他类处理,甚至忽略转发的消息而去做其他事情。
不过,到达消息转发需要经历前面的四步,也是一笔不小的开销,过多的依赖转发来响应消息会影响性能。
参考:
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Beginning ASP.NET 4 in C# and Vb
Imar Spaanjaars / Wrox / 2010-3-19 / GBP 29.99
This book is for anyone who wants to learn how to build rich and interactive web sites that run on the Microsoft platform. With the knowledge you gain from this book, you create a great foundation to ......一起来看看 《Beginning ASP.NET 4 in C# and Vb》 这本书的介绍吧!