Struct:
在结构体中办法都是静态调用(直接调用),也就意味着在在编译连接完成之后当时这个函数的地址就现已确定了,在函数履行的过程中就会直接去到这个地址来履行当时办法,这是结构体的办法调度
Class:
比较于结构体,在类中办法是存放在v-Table中
v-Table在sil中的表明: decl ::= sil-vtable sil-vtable ::= ‘sil-vtable’ identifier ‘{‘ sil-vtable-entry* ‘}’ sil-vtable-entry ::= sil-decl-ref ‘:’ sil-linkage? sil-function-name
v-Table代码解读:先声明sil-vtable这个关键字,这个关键字里边包括了第一‘sil-vtable’关键字,第二包括一个identifier(标识符)可所以类,然后{‘ sil-vtable-entry* ‘}代表着identifier中包括的所有办法,最终一段是办法声明和办法名称
验证办法一:汇编
源码:
import UIKit
class FFHobbyGirls {
func hobbyGirls() {print("hobbyGirls")}
func hobbyGirls1() {print("hobbyGirls1")}
func hobbyGirls2() {print("hobbyGirls2")}
func hobbyGirls3() {print("hobbyGirls3")}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
var t = FFHobbyGirls()
t.hobbyGirls()
t.hobbyGirls1()
t.hobbyGirls2()
t.hobbyGirls3()
}
}
arm64汇编指令
blr: 带回来的跳转指令,跳转到指令后边跟从寄存器中保存的地址
mov: 将某一寄存器的值复制到另一寄存器(只能用于寄存器与寄存器,或许寄存器与常量之间传值,不能用于内存地址) 比如:mov x1,x0 将寄存器x0的值复制到寄存器x1中
ldr: 将内存中的值读取到寄存器中 比如:ldr x0,[x1,x2] 将寄存器x1和寄存器x2相加作为地址,取该内存地址的值放入寄存器x0中
str: 将寄存器中的值写入内存中 比如:str x0,[x0, x8] 将寄存器x0的值写入内存[x0+x8]处
br : 跳转到某地址
图一:
结论:想要验证的是在v-table中函数地址是接连存储的!!!
子类承继父类,子类的v-table里边完好copy了父类里边的办法,采用的是以空间交换时刻的办法。
关于extension中的办法,调用的时分不经过v-table的办法了,是直接拜访内存地址。跟OC中是不同的
弥补OC中的分类: OC中办法调度是二维数组,Method_list,当呈现Category的时分,是将Method_list全体向后移动Category_list的内存空间,然后重新组合成了一个新的Class,这个时分会呈现一个问题:假如class中的办法与category中的办法呈现了重合,这个时分调用办法会优先调用到Category中的办法,原因是Category在整个Method_list的最前面。
final
final关键字:经过final关键字声明的办法会变成直接调用
@Objc
@Objc: 露出头文件给Objective-c调用,并不修正当时函数的调用办法,真实的状况是这里运用@objc之后,生成了两个相同的办法,其间一个是用@objc来标记的,在@objc标记的办法中调用了Swift v-table中的原办法。假如想真正的完全的给Objective-C来运用,那要使当时类承继NSObject。这个时分就ok了
Dynamic
dynamic:动态的。假如运用dynamic修饰的办法,当时类承继了NSObject,那么该办法就可以运用Method Swizzing
@objc dynamic
@objc dynamic: 假如一起运用这两个来修饰一个办法,那个这个办法的调度办法就会变成动态消息转发,检查汇编代码时当时此办法显现的是objc_msgSend
比如:
class FFHobbyGirls {
dynamic func hobbyGirls() {
print("hobbyGirls")
}
}
extension FFHobbyGirls {
@_dynamicReplacement(for: teach)
func teach1() {
print("teach1!")
}
}