DAY12: Closures

尾隨閉包(Trailing Closures)

如果你需要將一個很長的閉包表達式作為最后一個參數傳遞給函數,可以使用尾隨閉包來增強函數的可讀性,尾隨閉包是一個書寫在函數括號之后的閉包表達式,函數支持將其作為最后一個參數調用:

let digitNames = [
    0:"Zero",1:"One",2:"Two",3:"Three",4:"Four",
    5:"Five",6:"Six",7:"Seven",8:"Eight",9:"Nine"
]
let numbers = [16,58,510]

let strings = numbers.map {
    (var number) -> String in
    var output = ""
    while number > 0 {
        output = digitNames[number % 10]! + output
        number /= 10
    }
    return output
}

閉包語法:

{ (parameters) -> returnType in
    statements
}

map為數組中每一個元素調用了閉包表達式,不需要指定閉包輸入參數的類型,因為可以通過要映射的數組類型進行推斷。
在該例子中,閉包number參數被聲明為一個變量參數,因此可以在閉包函數體內對其進行修改,不用再定義一個局部變量并將number的值賦值給它,閉包表達式指定了返回類型為String,以表明存儲映射的新數組的類型是String,閉包表達式在每次被調用的時候創建了一個叫做output的字符串并且返回,使用求余(number % 10)計算最后一位數字并且利用digitNames字典獲取所映射的字符串,然后再除以10賦值給number.

比如16對10取余數是6,就獲取到了16的最后一位,然后16除以10賦值給number,number就是1,繼續循環,1對10取余數是1(商是0,余數是1),這時候number在除以10的時候,得到的就是0,下次循環的時候就不會繼續了。這個16輸入的就是OneSix。

總結:通過這個例子,我理解的閉包就是另外一個函數,我們通過封裝后,我們將數組的每個元素作為輸入,輸入給閉包函數,閉包進行轉換,輸出String。

捕獲值(Capturing Values)

閉包可以在其被定義的上下文中捕獲常量或者變量,及時定義了這些常量或者變量的作用域已經不存在,閉包仍然可以在閉包函數體內引用和修改這些值。
swift中可以捕獲值的閉包的最簡單的形式是嵌套函數,也就是定義在其他函數的函數體內的函數,嵌套函數可以捕獲其外部函數所有的參數以及定義的常量和變量。

func makeIncrementor(forIncrement amount: Int) -> () ->Int{
    var runningTotal = 0
    func incrementor() -> Int {
        runningTotal += amount
        return runningTotal
    }
    return incrementor
}

我們定義了一個嵌套函數makeIncrementor中嵌套了一個函數叫做incrementor,makeIncrementor這個函數返回的值是() ->Int,返回的是一個函數,不是一個值,返回的這個函數就是 incrementor,可以看見這個內嵌的函數沒有輸入值,輸出的值是Int類型的值,makeIncrementor入參是(forIncrement amount: Int) ,外部參數名字是forIncrement,內部的參數名是amount。

func incrementor() -> Int {
        runningTotal += amount
        return runningTotal
    }

可以看見這個函數并沒有任何的參數,單數函數體的內部訪問了runningTotal和amount,這兩個值是從外圍函數捕獲的runningTotal和amount變量的引用,捕獲引用保證了runningTotal和amount在調用完makeIncrementor后不會消失,并保證下次執行incrementor,runningTotal依舊存在。

let incrementByTen = makeIncrementor(forIncrement: 10)
incrementByTen()
// 返回的值為10
incrementByTen()
// 返回的值為20
incrementByTen()
// 返回的值為30

如果我們創建另一個incrementor,它擁有自己一個全新、獨立的runningTotal變量的引用,對incrementByTen的runningTotal沒有影響。

閉包是引用類型(Closures Are Reference Types)

func makeIncrementor(forIncrement amount: Int) -> () ->Int{
    var runningTotal = 0
    func incrementor() -> Int {
        runningTotal += amount
        return runningTotal
    }
    return incrementor
}
let incrementByTen = makeIncrementor(forIncrement: 10)

上面的例子incrementBySeven和incrementByTen是常量,但是這些常量指向的閉包仍然是可以增加其捕獲的變量的值,這是因為函數和閉包是引用類型。
無論您是講函數或者閉包賦值給一個常量或者變量,您實際上是將常量或者變量的值設定為對應的函數或者閉包的引用,上面的例子中,指向閉包的引用incrementByTen是一個常量,而非閉包內容本身。
這也就意味著,如果我們將閉包同時賦值給兩個不同的常量或者變量,兩個值都會指向同一個閉包:

let alsoIncrementByTen = incrementByTen
alsoIncrementByTen()

我們定義了一個變量,alsoIncrementByTen都是引用的同一個閉包,這個變量變化的話,我們定義的變量都會相應的變化。

非逃逸閉包(Nonescaping Closures)

當一個閉包作為參數傳入到另一個函數中,但是這個閉包在函數返回之后才被執行,我們稱該閉包從函數中逃逸,當你定義接收閉包作為參數的函數時,你可以在參數名前面標注@noescape,用來指明這個閉包是不允許“逃逸”出這個函數的。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,565評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,115評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 177,577評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,514評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,234評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,621評論 1 326
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,641評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,822評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,380評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,128評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,319評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,879評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,548評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,970評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,229評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,048評論 3 397
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,285評論 2 376

推薦閱讀更多精彩內容