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 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?