type
status
date
slug
summary
tags
category
icon
password
1、Table 表(Virtual Table)
1.1 VTable表(Virtual Table)
class 中默认的无@objc dynamic或者final修饰的方法或属性都是存在了 VTable 表中,VTable 是一个数组,里边存的是方法的地址.
age 属性在VTable表中也会存储 getter、setter、modify 方法
person 的 eat 方法地址会替换 Animal 的 eat 方法地址
person 的 say 方法会在 VTable 最后添加
查找方法为从 0 位移 offset
1.2 协议WTable(Witness Table)
WTable 是一个类似VTable的表,协议中的方法会存在于WTable中
2、静态派发(static dispatch)
静态派发
2.1、Extension
2.2、值类型
值类型的方法因为不支持继承关系,所以也是静态派发
2.3、final
添加了final关键字的方法编译器都会把该方法的派发改为静态派发
添加了final关键字的对象会把所有方法改为静态派发
2.4、Static
同2.3
3、消息转发(OC dynamic dispatch)
添加了@objc关键字之后,会生成两个函数,一个是Person.eat(),一个是 @objc Person.eat()
方法入口是@objc Person.eat()
@objc Person.eat()实现是调用Person.eat()
只添加@objc并不会调用OC的消息动态转发
添加@objc dynamic才会使用OC的动态消息转发:
extension 中加入 @objc 就是动态派发了
4、内联 inline
如果 sayHello 方法只调用较少次数,编译器在编译二进制文件时会省略 开辟函数空间、跳转到函数两个步骤,直接将 person.sayHello 替换为 print(”hello”),从而更加高效执行
内联详解
总结:
内联是最快的
其次是静态派发,因为省去了拿表、查表两个步骤
接着是查表,它需要去找到 Table,并去遍历 Table
OC的消息转发有多个步骤所以是最慢的,但是因为有cache的存在,在第一次调用方法时cache中不存在会消耗一些性能。但是cache存储之后,就和Table查找逻辑相同了
如果感觉这篇文章不那么清晰明了,可以参考详细案例:
- 作者:NotionNext
- 链接:https://tangly1024.com/article/Swift%20%E7%9A%84%E6%B6%88%E6%81%AF%E6%B4%BE%E5%8F%91
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
相关文章