因為inout
關鍵字比較簡單拢军,因此該文章篇幅相對比較短小楞陷。
我們直到在swift
中inout
通常用來在函數(shù)內(nèi)修改外部變量使用。那么其實我們也很容易聯(lián)想到在函數(shù)內(nèi)去修改class
對象的某個屬性茉唉,修改完成后我們在函數(shù)外部去訪問該屬性即是最新的值固蛾。
但如果我們需要修改的是一個局部變量或者我們需要修改的變量是一個私有變量,該變量并未聲明未public
那么此時我們在另一個類中需要修改其值時就比較麻煩了度陆。那么此時我們可以通過inout
來實現(xiàn)艾凯,這樣在不暴露私有變量的情況下即可走相同的邏輯。
class A {
private var a: Int = 1
func start() {
B.test(&a)
}
}
class B {
static func test(_ num: inout Int) {
num = 20
}
}
其實通過之前的匯編分析我們大致也可以直到inout
本質(zhì)上應該是將變量對應的地址傳入到了函數(shù)中懂傀,從而修改變量的值趾诗。 舉個??:
var age = 10
func test(_ num: inout Int) {
num = 20
}
test(&age)
此時斷點在test(&age)
處,進入到匯編代碼中蹬蚁。
image.png
可以看到在調(diào)用函數(shù)前往
rdi
中寫入的是地址信息恃泪,而rdi
常用作傳遞函數(shù)參數(shù)。這里就不多贅述了犀斋,相信根據(jù)前面的文章理解這里相對來說是很容易的贝乎。
下面我們主要來探究一下屬性的inout
使用
struct Test {
var a: Int
var b: Int {
willSet {
print("willset")
}
didSet {
print("didset")
}
}
var c: Int {
get {
return a * b
}
set {
b = a + 1
}
}
}
func test(_ num: inout Int) {
num = 20
}
let p = Test(a: 10, b: 20)
test(&p.a)
這里我們可以直接得到結(jié)論這邊函數(shù)傳入的就是屬性a
的地址。
image.png
我們可以看到第
15
行的說明信息已經(jīng)是很名曲額的將對象p
的地址放入到了rdi
中也就是將屬性a
的地址(注意這里的對象是個結(jié)構體)傳入到了函數(shù)中叽粹。
此時我們再將函數(shù)調(diào)用改為test(&p.c)
览效,也就是重寫屬性的getter
和setter
方法時。同樣直接看匯編虫几。
image.png
直接看第
18
锤灿,21
,24
行辆脸,可以看到現(xiàn)執(zhí)行getter
獲取到數(shù)據(jù)后并保存在一個地址中但校,然后調(diào)用test
函數(shù)時將該地址傳入,后續(xù)調(diào)用setter
方法時在傳入該地址每强。
再去通過匯編看屬性觀察器的實現(xiàn)其實也是大同小異始腾,不同點則是在函數(shù)調(diào)用完成后再去調(diào)用屬性的setter
方法,從而觸發(fā)屬性觀察器的方法空执。