閉包
閉包:一個(gè)函數(shù)和它所捕獲的變量\常量環(huán)境組合起來,稱為閉包
(一般它捕獲的是外層函數(shù)的局部變量\常量)
- 可以把閉包想象成是一個(gè)類的實(shí)例對(duì)象
- 捕獲的局部變量\常量就是對(duì)象的成員(存儲(chǔ)屬性)
- 組成閉包的函數(shù)就是類內(nèi)部定義的方法
func getFn() -> (Int) -> Int {
var num = 0
return {
num += $0;
return num;
}
}
var fn = getFn() // malloc堆地址 將外部變量num存入
print(fn(1)) // 1
print(fn(2)) // 3
print(fn(3)) // 6
print(fn(4)) // 10
print(getFn()(1)) // 1 malloc
print(getFn()(2)) // 2 malloc
print(getFn()(3)) // 3 malloc
print(getFn()(4)) // 4 malloc
反匯編查看
-
將局部變量注掉幔亥,觀察運(yùn)行過程中并沒有調(diào)用 swiftallocObject耻讽,并沒有向堆空間申請(qǐng)地址。
-
使用局部變量時(shí)帕棉,閉包內(nèi)部需要捕獲外部的局部變量/常量针肥,存儲(chǔ)在堆空間中。 打印 rax香伴,獲取閉包在堆空間保存變量的地址的位置慰枕。
-
將斷點(diǎn)打在 num 變化處,去堆空間地址中查看存儲(chǔ)數(shù)值是否發(fā)生改變即纲,若能對(duì)應(yīng)得上具帮,則證明猜想正確。
練習(xí)
typealias Fn = (Int) -> (Int, Int)
func getFns() -> (Fn, Fn) {
// 分別創(chuàng)建兩個(gè)地址保存低斋,但數(shù)據(jù)是共用的
var num1 = 0 // malloc num1
var num2 = 0 // malloc num2
func plus(_ i: Int) -> (Int, Int) {
num1 += i
num2 += i << 1 // *2
return (num1, num2)
}
func minus(_ i: Int) -> (Int, Int) {
num1 -= i
num1 -= i << 1
return (num1, num2)
}
return (plus, minus)
}
// 把閉包想象成是一個(gè)類的實(shí)例對(duì)象,捕獲的局部變量\常量就是對(duì)象的成員
let (p, m) = getFns()
print(p(5)) // (5, 10)
print(m(4)) // (1, 2)
print(p(3)) // (4, 8)
print(m(2)) // (2, 4)