26.Swift方法调度
纯 Swift 类
普通函数
class RyukieSwiftClass {
var age: String?
func hello() {
print(age ?? "-")
}
}
let ry = RyukieSwiftClass()
ry.age = "Ryukie"
ry.hello()生成 SIL 文件,找到:
sil_vtable RyukieSwiftClass {
#RyukieSwiftClass.age!getter: (RyukieSwiftClass) -> () -> String? : @main.RyukieSwiftClass.age.getter : Swift.String? // RyukieSwiftClass.age.getter
#RyukieSwiftClass.age!setter: (RyukieSwiftClass) -> (String?) -> () : @main.RyukieSwiftClass.age.setter : Swift.String? // RyukieSwiftClass.age.setter
#RyukieSwiftClass.age!modify: (RyukieSwiftClass) -> () -> () : @main.RyukieSwiftClass.age.modify : Swift.String? // RyukieSwiftClass.age.modify
#RyukieSwiftClass.hello: (RyukieSwiftClass) -> () -> () : @main.RyukieSwiftClass.hello() -> () // RyukieSwiftClass.hello()
#RyukieSwiftClass.init!allocator: (RyukieSwiftClass.Type) -> () -> RyukieSwiftClass : @main.RyukieSwiftClass.__allocating_init() -> main.RyukieSwiftClass // RyukieSwiftClass.__allocating_init()
#RyukieSwiftClass.deinit!deallocator: @main.RyukieSwiftClass.__deallocating_deinit // RyukieSwiftClass.__deallocating_deinit
}可见:纯 Swift 类的函数,是存在一个 sil_vtable 类型的数据结构内的。
@objc、dynamic、@objc dynamic 关键字修饰的函数
对上面代码进行修改
SIL:
通过 SIL 我们发现:普通函数、@objc 函数 和 dynamic 函数 都是通过 sil_vtable 存储的,而且内存空间连续。
但是 sil_vtable 内部少了 @objc dynamic 修饰的函数。我们通过汇编断点看一下:

图中我们发现 @objc dynamic 修饰的函数,是通过 objc_msgSend 进行调度的,所以并不在 sil_vtable 内。
extension
我们新增一个 extension 并调用其中的函数:
汇编端点发现 call 0x1000037e0 是直接通过地址调用的:
且在 sil_vtable 结构中没有发现 extensionHello。
所以:在 Swift 类的 extension 中的函数是 静态调用 的。
子类
我们定义一个子类:
SIL:
汇编端点:
我们发现子类的 sil_vtable 结构中包含了父类的结构,自己专有的部分跟在父类的结构之后。
子类的方法调度,没有特殊的方法变化。
override
如果重写父类方法呢?
SIL 会有些许变化:
final
静态调度,不会存在于 vtable 中
private fileprivate 的会被自动优化为 final
sil_vtable
我们找到 initClassVTable 源码:
通过源码我们发现 sil_vtable 内部是一个数组的结构,通过下标读写。
结构体
汇编断点:
发现都是通过地址直接静态调用的。
Last updated
Was this helpful?