Comment on page
26.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 类型的数据结构内的。
对上面代码进行修改
class RyukieSwiftClass {
var age: String?
func hello() {
print("hello: \(age ?? "-")")
}
dynamic func dynamicHelo() {
print("dynamic: \(age ?? "-")")
}
@objc func atObjcHello() {
print("@objc: \(age ?? "-")")
}
@objc dynamic func atObjcDynamicHello() {
print("@objc dynamic: \(age ?? "-")")
}
}
let ry = RyukieSwiftClass()
ry.age = "Ryukie"
ry.hello()
ry.dynamicHelo()
ry.atObjcHello()
ry.atObjcDynamicHello()
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()
// dynamic 函数
#RyukieSwiftClass.dynamicHelo: (RyukieSwiftClass) -> () -> () : @main.RyukieSwiftClass.dynamicHelo() -> () // RyukieSwiftClass.dynamicHelo()
// @objc 函数
#RyukieSwiftClass.atObjcHello: (RyukieSwiftClass) -> () -> () : @main.RyukieSwiftClass.atObjcHello() -> () // RyukieSwiftClass.atObjcHello()
#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
}
通过 SIL 我们发现:
普通函数
、@objc 函数
和 dynamic 函数
都是通过 sil_vtable
存储的,而且内存空间连续。但是
sil_vtable
内部少了 @objc dynamic
修饰的函数。我们通过汇编断点看一下:
@objc dynamic
图中我们发现
@objc dynamic
修饰的函数,是通过 objc_msgSend
进行调度的,所以并不在 sil_vtable
内。我们新增一个 extension 并调用其中的函数:
extension RyukieSwiftClass {
func extensionHello() {
print("extension: \(age ?? "-")")
}
}
汇编端点发现
call 0x1000037e0
是直接通过地址调用的:-> 0x1000029d9 <+73>: mov r13, qword ptr [rip + 0x58a0] ; SourceCodeStudy.ry : SourceCodeStudy.RyukieSwiftClass
0x1000029e0 <+80>: call 0x1000037e0 ; SourceCodeStudy.RyukieSwiftClass.extensionHello() -> () at main.swift:35
且在
sil_vtable
结构中没有发现 extensionHello
。所以:在 Swift 类的 extension 中的函数是 静态调用 的。
我们定义一个子类:
class RyukieSwiftSubClass: RyukieSwiftClass {
func subHello() {
print("sub: \(age ?? "-")")
}
}
let subRy = RyukieSwiftSubClass()
subRy.age = "18"
subRy.hello()
subRy.subHello()
subRy.extensionHello()
SIL:
sil_vtable RyukieSwiftSubClass {
// 父类的结构
#RyukieSwiftClass.age!getter: (RyukieSwiftClass) -> () -> String? : @main.RyukieSwiftClass.age.getter : Swift.String? [inherited] // RyukieSwiftClass.age.getter
#RyukieSwiftClass.age!setter: (RyukieSwiftClass) -> (String?) -> () : @main.RyukieSwiftClass.age.setter : Swift.String? [inherited] // RyukieSwiftClass.age.setter
#RyukieSwiftClass.age!modify: (RyukieSwiftClass) -> () -> () : @main.RyukieSwiftClass.age.modify : Swift.String? [inherited] // RyukieSwiftClass.age.modify
#RyukieSwiftClass.hello: (RyukieSwiftClass) -> () -> () : @main.RyukieSwiftClass.hello() -> () [inherited] // RyukieSwiftClass.hello()
#RyukieSwiftClass.dynamicHelo: (RyukieSwiftClass) -> () -> () : @main.RyukieSwiftClass.dynamicHelo() -> () [inherited] // RyukieSwiftClass.dynamicHelo()
#RyukieSwiftClass.atObjcHello: (RyukieSwiftClass) -> () -> () : @main.RyukieSwiftClass.atObjcHello() -> () [inherited] // RyukieSwiftClass.atObjcHello()
// 自己的结构
#RyukieSwiftClass.init!allocator: (RyukieSwiftClass.Type) -> () -> RyukieSwiftClass : @main.RyukieSwiftSubClass.__allocating_init() -> main.RyukieSwiftSubClass [override] // RyukieSwiftSubClass.__allocating_init()
#RyukieSwiftSubClass.subHello: (RyukieSwiftSubClass) -> () -> () : @main.RyukieSwiftSubClass.subHello() -> () // RyukieSwiftSubClass.subHello()
#RyukieSwiftSubClass.deinit!deallocator: @main.RyukieSwiftSubClass.__deallocating_deinit // RyukieSwiftSubClass.__deallocating_deinit
}