閉包是自包含的函數代碼塊,能夠在代碼中被傳遞和使用。Swift中的閉包與C和Objective-C中的代碼塊(blocks)以及其餘一些編程語言中的Lambda函數比較類似。在本章中所講的函數其實就是特殊的閉包。本節主要講解關於閉包的基本使用。git
閉包表達式是一種利用簡潔語法構建內聯(內聯相似與C語言中的宏定義)閉包的方式。如下這個代碼是對兩個字符串的比較。編程
import Foundation數組
//判斷兩個字符串的大小閉包
func compare(s1: String, s2: String) -> Bool {編程語言
return s1 > s2函數
}spa
let str1="Hello"orm
let str2="Swift"教程
if compare(str1, s2: str2) {開發
print("str1大於str2")
}else{
print("str1小於str2")
}
運行結果以下:
str1小於str2
在此代碼中,當調用函數compare()時,會將str1和str2傳遞到給函數在定義時的參數s1,s2中,而後進行比較。在此代碼中能夠看到,在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()函數時,會將參數array、40以及閉包表達式傳遞到函數定義的參數中,在copare()函數中,遍歷數組中元素的時候,又會去調用閉包表達式。運行結果以下:
數組array中沒有比500大的元素
數組array中有比40大的元素
在使用閉包表達式時須要注意如下幾點(如下都是以示例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.運算符函數
在Swift中String類型定義了關於大於號(>)的字符串實現,其做爲一個函數接受兩個String類型的參數並返回Bool類型的值。而這正好與以上代碼sort函數的第二個參數須要的函數類型相符合。 所以,能夠簡單地傳遞一個大於號,Swift能夠自動推斷出您想使用大於號的字符串函數實現:
var v1=copare(array,value:500,cb:>)
在Swift 1.2中使用閉包表達式須要注意如下三點:
q 有單返回語句的閉包,如今類型檢查時以單表達式閉包處理。
q 匿名的且含有非空返回類型的單表達式,如今能夠用在void上下文中。
q 多表達式的閉包類型的狀況,可能沒法被類型推斷出來。
若是開發者須要將一個很長的閉包表達式做爲最後一個參數傳遞給函數,可使用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閉包的形式。
閉包能夠在其定義的上下文中捕獲常量或變量。如下就使用incrementor()函數從上下文種對值runningTotal和amount進行捕獲。代碼以下:
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人!