閉包可以在其定義的上下文中捕獲常量或變量。 即使定義這些常量和變量的原域已經(jīng)不存在,閉包仍然可以在閉包函數(shù)體內(nèi)引用和修改這些值。
Swift最簡單的閉包形式是嵌套函數(shù),也就是定義在其他函數(shù)的函數(shù)體內(nèi)的函數(shù)。 嵌套函數(shù)可以捕獲其外部函數(shù)所有的參數(shù)以及定義的常量和變量。
下例為一個(gè)叫做makeIncrementor的函數(shù),其包含了一個(gè)叫做incrementor嵌套函數(shù)。 嵌套函數(shù)incrementor從上下文中捕獲了兩個(gè)值,runningTotal和amount。 之后makeIncrementor將incrementor作為閉包返回。 每次調(diào)用incrementor時(shí),其會(huì)以amount作為增量增加runningTotal的值。
func makeIncrementor(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementor() -> Int {
runningTotal += amount
return runningTotal
}
return incrementor
}
makeIncrementor返回類型為() -> Int。 這意味著其返回的是一個(gè)函數(shù),而不是一個(gè)簡單類型值。 該函數(shù)在每次調(diào)用時(shí)不接受參數(shù)只返回一個(gè)Int類型的值。 關(guān)于函數(shù)返回其他函數(shù)的內(nèi)容,請(qǐng)查看函數(shù)類型作為返回類型。
makeIncrementor函數(shù)定義了一個(gè)整型變量runningTotal(初始為0) 用來存儲(chǔ)當(dāng)前跑步總數(shù)。 該值通過incrementor返回。
makeIncrementor有一個(gè)Int類型的參數(shù),其外部命名為forIncrement, 內(nèi)部命名為amount,表示每次incrementor被調(diào)用時(shí)runningTotal將要增加的量。
incrementor函數(shù)用來執(zhí)行實(shí)際的增加操作。 該函數(shù)簡單地使runningTotal增加amount,并將其返回。
如果我們單獨(dú)看這個(gè)函數(shù),會(huì)發(fā)現(xiàn)看上去不同尋常:
func incrementor() -> Int {
runningTotal += amount
return runningTotal
}
incrementor函數(shù)并沒有獲取任何參數(shù),但是在函數(shù)體內(nèi)訪問了runningTotal和amount變量。這是因?yàn)槠渫ㄟ^捕獲在包含它的函數(shù)體內(nèi)已經(jīng)存在的runningTotal和amount變量而實(shí)現(xiàn)。
由于沒有修改amount變量,incrementor實(shí)際上捕獲并存儲(chǔ)了該變量的一個(gè)副本,而該副本隨著incrementor一同被存儲(chǔ)。
然而,因?yàn)槊看握{(diào)用該函數(shù)的時(shí)候都會(huì)修改runningTotal的值,incrementor捕獲了當(dāng)前runningTotal變量的引用,而不是僅僅復(fù)制該變量的初始值。捕獲一個(gè)引用保證了當(dāng)makeIncrementor結(jié)束時(shí)候并不會(huì)消失,也保證了當(dāng)下一次執(zhí)行incrementor函數(shù)時(shí),runningTotal可以繼續(xù)增加。
注意:
Swift 會(huì)決定捕獲引用還是拷貝值。
您不需要標(biāo)注amount或者runningTotal來聲明在嵌入的incrementor函數(shù)中的使用方式。
Swift 同時(shí)也處理runingTotal變量的內(nèi)存管理操作,如果不再被incrementor函數(shù)使用,則會(huì)被清除。
下面代碼為一個(gè)使用makeIncrementor的例子:
let incrementByTen = makeIncrementor(forIncrement: 10)
上一篇:Swift存儲(chǔ)型屬性的初始賦值下一篇:Swift 反初始化