標籤:
http://blog.csdn.net/huangchentao/article/details/32714185
閉包 Closures
1.閉包運算式
閉包運算式是一種利用簡單文法構建內聯包的方式,提供一些文法最佳化,使得閉包代碼變得更加簡單明了
1.1sort函數
Swift標準庫提供了sort函數,將已知類型數組中的值進行排序,返回一個與原數組大小相等但元素已正確排序的數組
sort函數需要傳入兩個參數:
1.已知類型的數組
2.傳入兩個跟數組相同型別參數的閉包函數,並返回一個布爾值告訴sort函數排序結束後傳入的第一個參數排在第二個參數的前面還是後面,如果第一個參數值出現在第二個參數值前面,排序閉包函數需要返回true,否則返回false
[objc] view plaincopy
- let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
該例子對String類型的數組進行排序,因此該排序閉包函數類型為 (String, String) -> Bool
提供排序閉包函數的另一種方式是寫一個符合其類型要求的普通函數,並將其作為sort函數的第二個參數傳入
[objc] view plaincopy
- func backwards(s1: String, s2: String) -> Bool {
- return s1 > s2
- }
- var reversed = sort(names, backwards)
- // reversed is equal to ["Ewa", "Daniella", "Chris", "Barry", "Alex"]
1.2閉包運算式文法
閉包運算式一般形式,可以使用常量、變數和inout類型作為參數,不提供預設值,也可以在參數列表後面使用可變參數。元組也可以作為參數和傳回值
[objc] view plaincopy
- { (parameters) -> return type in
- statements
- }
- // backwards函數對應的閉包運算式版本,閉包的函數體部分由關鍵字 in 引入
- // 該關鍵字表示閉包的參數和傳回值類型定義已經完成,閉包函數體開始
- reversed = sort(names, { (s1: String, s2: String) -> Bool in
- return s1 > s2
- })
-
- // 簡寫形式
- reversed = sort(names, { (s1: String, s2: String) -> Bool in return s1 > s2 } )
1.3根據上下文推斷類型
因為排序閉包函數是作為sort函數的參數進行傳入,Swift可以判斷其參數和傳回值的類型
[objc] view plaincopy
- reversed = sort(names, { s1, s2 in return s1 > s2 } )
1.4單行運算式閉包隱式返回
單行運算式閉包可以通過隱藏return關鍵字來隱式返回單行運算式的結果
[objc] view plaincopy
- reversed = sort(names, { s1, s2 in s1 > s2 } )
1.5參數名稱縮寫
Swift自動為內嵌函式提供了參數名稱縮寫功能,可直接通過 $0,$1,$2 來順序調用閉包的參數。如果您在閉包運算式中使用參數名稱縮寫,可以在閉包參數列表中省略對其的定義,並且對應參數名稱縮寫的類型會通過函數類型進行推斷。 in關鍵字也同樣可以被省略,因為此時閉包運算式完全由閉包函數體構成
[objc] view plaincopy
- reversed = sort(names, { $0 > $1 } )
1.6運算子函數
Swift 的String類型定義了關於大於符號 (>) 的字串實現,其作為一個函數接受兩個String類型的參數並返回Bool類型的值。 而這正好與sort函數的第二個參數需要的函數類型相符合。 因此可以簡單地傳遞一個大於符號,Swift可以自動推斷出您想使用大於符號的字串函數實現
[objc] view plaincopy
- reversed = sort(names, >)
2.尾隨閉包
如果需要將一個很長的閉包運算式作為最後一個參數傳遞給函數,可以使用尾隨閉包來增強函數的可讀性。如果函數只需要閉包運算式一個參數,當使用尾隨閉包時,甚至可以把()省略掉。
[objc] view plaincopy
- func someFunctionThatTakesAClosure(closure: () -> ()) {
- // function body goes here
- }
-
- // 以下是不使用尾隨閉包進行函數調用
- someFunctionThatTakesAClosure({
- // closure‘s body goes here
- })
-
- // 以下是使用尾隨閉包進行函數調用
- someFunctionThatTakesAClosure() {
- // trailing closure‘s body goes here
- }
-
- //在上例中作為sort函數參數的字串排序閉包可以改寫為:
- reversed = sort(names) { $0 > $1 }
-
-
- 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
- }
- // strings is inferred to be of type String[]
- // its value is ["OneSix", "FiveEight", "FiveOneZero"]
3.值捕獲
閉包可以在其定義的上下文中捕獲常量或變數。即使定義這些常量和變數的原域已經不存在,閉包仍然可以在閉包函數體內引用和修改這些值。Swift最簡單的閉包形式是嵌套函數,也就是定義在其他函數的函數體內的函數。 嵌套函數可以捕獲其外部函數所有的參數以及定義的常量和變數。
[objc] view plaincopy
- func makeIncrementor(forIncrement amount: Int) -> () -> Int {
- var runningTotal = 0
- func incrementor() -> Int {
- runningTotal += amount
- return runningTotal
- }
- return incrementor
- }
-
-
- func incrementor() -> Int {
- runningTotal += amount
- return runningTotal
- }
-
-
- let incrementByTen = makeIncrementor(forIncrement: 10)
-
-
- incrementByTen()
- // returns a value of 10
- incrementByTen()
- // returns a value of 20
- incrementByTen()
- // returns a value of 30
-
-
- let incrementBySeven = makeIncrementor(forIncrement: 7)
- incrementBySeven()
- // returns a value of 7
- incrementByTen()
- // returns a value of 40
4.閉包是參考型別
無論將函數/閉包賦值給一個常量還是變數,實際都是將常量/變數的值設定為對應函數/閉包的引用,如果將閉包賦給了兩個不同的常量/變數,兩個值都會指向同一個閉包
[objc] view plaincopy
- let alsoIncrementByTen = incrementByTen
- alsoIncrementByTen()
- // returns a value of 50
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
Swift 閉包(六)