Swift2.0語言教程之閉包

大學霸發表於2015-07-20

Swift2.0語言教程之閉包

Swift2.0語言閉包

閉包是自包含的函式程式碼塊,可以在程式碼中被傳遞和使用。Swift中的閉包與CObjective-C中的程式碼塊(blocks)以及其他一些程式語言中的Lambda函式比較相似。在本章中所講的函式其實就是特殊的閉包。本節主要講解關於閉包的基本使用。

Swift2.0語言閉包表示式

閉包表示式是一種利用簡潔語法構建內聯(內聯類似與C語言中的宏定義)閉包的方式。以下這個程式碼是對兩個字串的比較。

  • import Foundation

  • //判斷兩個字串的大小

  • func compare(s1: String, s2: String) -> Bool {

  •     return s1 > s2

  • }

  • let str1="Hello"

  • let str2="Swift"

  • if compare(str1, s2: str2) {

  •     print("str1大於str2")

  • }else{

  •     print("str1小於str2")

  • }

執行結果如下:

  • str1小於str2

在此程式碼中,當呼叫函式compare()時,會將str1str2傳遞到給函式在定義時的引數s1s2中,然後進行比較。在此程式碼中可以看到,在compare()函式中執行了一行程式碼,就是判斷並返回,顯的此函式相當冗長。此時就可以使用閉包表示式使用程式碼變得更好。首先,來看一下閉包表示式(閉包函式)的語法形式。

  • {(引數列表)->返回值型別 in

  •    語句

  • }

其中,引數可以是常量、變數和輸入-輸出引數,但沒有預設值。開發者也可以在引數列表的最後使用可變引數。而元組也可以作為引數和返回值。關鍵字in表示閉包的引數和返回值型別定義已經完成,閉包函式體即將開始。

1.無參形式的閉包表示式

無參形式的閉包表示式語法形式如下:

  • {()->返回值型別 in

  •    語句

  • }

它定義的語法形式如下:

  • let/var 閉包表示式常量名稱/閉包表示式變數名稱/=無參形式的閉包表示式

它呼叫的語法形式如下:

  • 閉包表示式常量名稱/閉包表示式變數名稱()

【示例7-27】以下將使用閉包表示式實現字串"aaaa"的輸出。程式碼如下:

  • import Foundation

  • //輸出字串"aaaa"

  • var str={() in

  • print("aaaa")

  • }

  • str()                                                //呼叫的呼叫形式

執行結果如下:

  • aaaa

2.具有引數的閉包表示式

具有引數的閉包表示式有兩種形式一種是最常用的只有一個引數的閉包表示式;一種是具有多個引數的閉包表示式。以下是對這兩種具有引數的閉包表示式的詳細講解。

1具有一個引數的閉包表示式

具有一個引數的閉包表示式的語法形式如下:

  • {(引數名:資料型別)->返回值型別 in

  •    語句

  • }

它定義的語法形式如下:

  • let/var 閉包表示式常量名稱/閉包表示式變數名稱/=具有一個引數的閉包表示式

它的呼叫形式如下:

  • 閉包表示式常量名稱/閉包表示式變數名稱()

【示例7-28】以下將使用閉包表示式輸出指定字串。程式碼如下:

  • import Foundation

  • //輸出指定的字串

  • var str={(str:String) in

  •     print(str)

  • }

  • str("Hello")

執行結果如下:

  • Hello

2具有多個引數的閉包表示式

具有多個引數的閉包表示式的語法形式如下:

  • {(引數名1:資料型別,引數名2:資料型別,)->返回值型別 in

  •    語句

  • }

它定義的語法形式如下:

  • let/var 閉包表示式常量名稱/閉包表示式變數名稱/=具有多個引數的閉包表示式

它的呼叫形式如下:

  • 閉包表示式常量名稱/閉包表示式變數名稱()

【示例7-29】使用閉包實現對兩個任意數的求和計算,程式碼如下:

  • import Foundation

  • //實現求兩個數的和

  • var reversed = {(s1: Int, s2: Int) -> Int in

  • var sum=s1+s2

  • return sum

  • }

  • print(reversed(10,20))

執行結果如下:

  • 30

其實閉包表示式最長用在其他的函式中,並不是單獨的去使用它。

【示例7-30】以下程式碼將閉包表示式作為函式的一部分,來實現在判斷在陣列中是否有大於500或者40的元素。程式碼如下:

  • import Foundation

  • //定義函式

  • func copare(arr:[Int],value:Int,cb:(Num:Int,Value:Int)->Bool)->Bool{

  •     //遍歷陣列

  •     for item in arr{

  •         //判斷閉是否為真

  •         if(cb(Num: item,Value: value)){

  •             return true

  •         }

  •     }

  •     return false

  • }

  • var array = [20,80,100,50,20]

  • //使用閉包判斷是否在陣列中有大於500的元素

  • var v1=copare(array,value: 500,cb: {(num:Int,value:Int)->Bool in

  •     return num>value

  • })

  • //判斷結果並輸出·

  • if  v1==true {

  •     print("陣列array中有比500大的元素")

  • }else{

  •     print("陣列array中沒有比500大的元素")

  • }

  • //使用閉包判斷是否在陣列中有大於40的元素

  • var v2=copare(array,value: 40,cb: {(num:Int,value:Int)->Bool in

  •     return num>value

  • })

  • //判斷結果並輸出

  • if  v2==true {

  •     print("陣列array中有比40大的元素")

  • }else{

  •     print("陣列array中沒有比40大的元素")

  • }

在此程式碼中,當呼叫copare()函式時,會將引數array40以及閉包表示式傳遞到函式定義的引數中,在copare()函式中,遍歷陣列中元素的時候,又會去呼叫閉包表示式。執行結果如下:

  • 陣列array中沒有比500大的元素

  • 陣列array中有比40大的元素

Swift2.0語言使用閉包表示式的注意事項

在使用閉包表示式時需要注意以下幾點(以下都是以示例7-30來說明的):

1.推斷型別

copare()函式的第三個引數是閉包表示式,它的型別為(num:Int,value:Int)->Bool,由於Swift可以推斷其引數和返回值的型別,所以->和圍繞在引數周圍的括號可以省略,如以下的程式碼:

  • var v1=copare(array,value:500,cb:{(num,value) in

  •      return num>value

  • })

2.省略return

單行表示式閉包可以透過隱藏return關鍵字來隱式返回單行表示式的結果,可以將上面的例子進行修改:

  • var v1=copare(array,value:500,cb:{(num,value) in

  •      num>value

  • })

3.簡寫引數名

Swift為行內函數提供了引數名縮寫功能,開發者可以透過$0$1$2來順序的呼叫閉包的引數。如果在閉包表示式中使用引數名稱縮寫,可以在閉包引數列表中省略對其的定義,並且對應引數名稱縮寫的型別會透過函式型別進行推斷。in關鍵字也同樣可以被省略,因為此時閉包表示式完全由閉包函式體構成,將上面的例子進行修改:

  • var v1=copare(array, value:500,cb: {

  •     $0 > $1

  • })

4.寫在一行

當閉包的函式體部分很短時可以將其寫在一行上面,如以下程式碼:

  • var v1=copare(array,value: 500,cb: {$0 > $1})

5.運算子函式

SwiftString型別定義了關於大於號(>)的字串實現,其作為一個函式接受兩個String型別的引數並返回Bool型別的值。而這正好與以上程式碼sort函式的第二個引數需要的函式型別相符合。 因此,可以簡單地傳遞一個大於號,Swift可以自動推斷出您想使用大於號的字串函式實現:

  • var v1=copare(array,value:500,cb:>)

Swift 1.2中使用閉包表示式需要注意以下三點:

  • q  有單返回語句的閉包,現在型別檢查時以單表示式閉包處理。

  • q  匿名的且含有非空返回型別的單表示式,現在可以用在void上下文中。

  • q  多表示式的閉包型別的情況,可能無法被型別推斷出來。

Swift2.0語言Trailing閉包

如果開發者需要將一個很長的閉包表示式作為最後一個引數傳遞給函式,可以使用Trailing閉包,它可以增強函式的可讀性。Trailing閉包的一般形式如下:

  • func someFunctionThatTakesAClosure(closure: () -> ()) {

  •     //函式主體部分

  • }

  • //以下不是使用trailing閉包進行的函式呼叫

  • someFunctionThatTakesAClosure({

  •          //閉包主體部分

  • })

  • //以下是使用trailing閉包進行的函式呼叫

  • someFunctionThatTakesAClosure() {

  •          //閉包主體部分

  • }

注意:trailing閉包是一個寫在函式括號之後的閉包表示式,函式支援將其作為最後一個引數呼叫。示例7-30中程式碼也可以寫為Trailing閉包,程式碼如下:

  • import Foundation

  • func copare(arr:[Int],value:Int,cb:(Num:Int,Value:Int)->Bool)->Bool{

  • for item in arr{

  •         if(cb(Num: item,Value: value)){

  •             return true

  •         }

  •     }

  •     return false

  • }

  • var array = [20,80,100,50,20]

  • var v1=copare(array,value:500) {(num:Int,value:Int)->Bool in

  •     return num>value

  • }

  • if  v1==true {

  •     print("陣列array中有比500大的元素")

  • }else{

  •     print("陣列array中沒有比500大的元素")

  • }

Trailing閉包一般使用在當閉包很長以至於不能在一行進行編寫的程式碼中。如以下的例子就使用了Trailing閉包,實現將數字改為英文的功能。程式碼如下:

  • import Foundation

  • //建立字典

  • let digitNames = [

  •     0: "Zero", 1: "One", 2: "Two",   3: "Three", 4: "Four",5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"

  • ]

  • //建立陣列

  • let numbers = [521,52,1,13,14]

  • //以下是使用trailing閉包進行的函式呼叫,實現將數字轉為英文        

  • let strings = numbers.map {

  •     (var number) -> String in

  •     var output = ""

  •     while number > 0 {

  •         output = digitNames[number % 10]! + output

  •         number /= 10

  •     }

  •     return output

  • }

  • //遍歷並輸出

  • for index in strings{

  •     print(index)

  • }

執行結果如下所示:

  • FiveTwoOne

  • FiveTwo

  • One

  • OneThree

  • OneFour

注意:在此程式碼中使用到了函式map(),它的功能是返回一個新的序列。其語法形式如下:

  • map(序列,閉包表示式)

其中,如果閉包表示式適用於序列中的所有元素,就會返回一個新的序列。但是在本示例中由於閉包中的內容比較多,就將它使用了Trailing閉包的形式。

Swift2.0語言捕獲值

閉包可以在其定義的上下文中捕獲常量或變數。以下就使用incrementor()函式從上下文種對值runningTotalamount進行捕獲。程式碼如下:

  • import Foundation

  • func makeIncrementor(forIncrement amount: Int) -> () -> Int {

  • var runningTotal = 0

  • //定義函式incrementor(),實現runningTotal的增加

  •     func incrementor() -> Int {

  •         runningTotal += amount

  •         return runningTotal

  •     }

  •     return incrementor

  • }

  • //賦值

  • var a = makeIncrementor(forIncrement: 10)

  • //輸出

  • print("輸出a的增量")

  • print(a())

  • print(a())

  • print(a())

  • var b = makeIncrementor(forIncrement: 5)

  • //賦值,輸出

  • print("輸出b的增量")

  • print(b())

  • print(b())

  • print(b())

執行結果如下所示:

  • 輸出a的增量

  • 10

  • 20

  • 30

  • 輸出b的增量

  • 5

  • 10

  • 15

本文選自:Swift2.0語言快速入門v3.0 大學霸內部資料,轉載請註明出處,尊重技術尊重IT人!


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29597077/viewspace-1741981/,如需轉載,請註明出處,否則將追究法律責任。

相關文章