Swift 閉包
函數 ()->()
Swift 中的閉包和 Objective-C 中的 block 類似,閉包是功能性自包含模塊,可以在代碼中被傳遞和使用。 在 Swift 中 函數只是閉包的一種特殊形式。
1.全局函數是一個有名字但不會捕獲任何值的閉包
2.內嵌函數是一個有名字可以捕獲到所在的函數域內值的閉包
3.閉包表達式是一個沒有名字的可以捕獲上下文中的變量或者常量的閉包
定義函數
我們在 Swift 中使用 func
關鍵字來定義函數,函數可以沒有參數和返回值,也可以有一個或者多個參數和返回值。在Swift中多個參數的返回值叫做元組(tuples
)
func foo(firstname:String ,lastname:String)->(fullname:String){
return("\(firstname) \(lastname)")
}
函數調用
let fullname = foo("zhao”,”sunny”)
函數類型
每一個函數都有它的類型,函數的類型由函數本身的參數類型和返回值類型來決定的。
func sum(x:Int,y:Int) -> (result:Int){return x + Y}
上面這個函數的函數類型就是
(Int,Int)->(Int)
函數類型在構建函數的時候當成參數類型或者返回值類型來使用。
返回函數類型
func foo()->((String,String) -> String){
func bar(firstname:String,lastname:String) ->(fullname:String){
return("\(firstname) \(lastname)")
}
return bar
}
let namecombination = foo()
namecombination("wang","er")
可變參數函數
可變參數函數是指函數可以接收不固定個參數。在參數類型后面添加 … 來標記這個參數為可變參數。我們可以在函數中像訪問數組一樣訪問可變參數。
func foo(names:String...) ->() {
for name in names {
println("\(name)")
}
}
func foo("zhao","zhang","wang")
In-out 參數函數
傳入函數的參數值只能在函數域內改變。參數傳遞是值傳遞,也就是說我們在函數內部修改了一個參數的值,在函數結束后,函數外部訪問到的參數值還是傳入函數之前的值,它并沒有隨著函數內的修改而改變。在Objective-C 我們通過指針來保存函數內修改過的值以供函數結束后外部訪問。常見的例子就是 NSError
的使用。
在Swift 中我們也可以做類似的操作。我們需要inout
關鍵字來標記要修改的參數。
func swapTwoInts(inout a: Int, inout b: Int) {
let temporaryA = a
a = b
b = temporaryA
}
var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
閉包 { ()->() in }
定義一個閉包
閉包是一個使用花括號{}
包圍起來,并且使用函數類型()->()
來定義的代碼模塊。->
符號分割了輸入參數和返回值類型。在關鍵字 in
來區分閉包的頭和閉包函數體。
{(params) -> returnType in
statements
}
一個數組的map
閉包的例子
let names = ["zhao","wang","Li"]
names.map({
(name:String) -> String in
"\(name) has been map !"
})
已知參數類型的閉包
map
的閉包是作為函數參數傳入的,所以 Swift 是可以做類型推斷的,這樣的話我們就不需要在閉包中在描述閉包的函數類型,也就是我們可以省略 (String) -> (String)
部分,來簡寫閉包表達式
let names = ["zhao","wang","Li"]
names.map({
name in
"\(name) has been map !"
})
如果閉包有返回值我們也可以簡寫省略掉return
。
例如
let names = ["zhao","wang","Li"]
let orderNames = sort(names,{s1,s2 in s1 > s2})
閉包參數名簡寫
Swift 為內聯函數提供了參數名稱簡寫功能,您可以直接通過 $0,$1,$2等名字來引用的閉包的參數的值。
let names = ["zhao","wang","Li"]
names.map({"\($0) has been map !"})
sort(names,{$0 > $1})
如果閉包是函數的最后一個參數,我們可以省略掉圓括號
names.map{"\($0) has been map !"}
sort(names){$0 > $1}
對于排序函數 sort()
來說作為參數的閉包表達式只進行了兩個值的比較,比較是通過操作符 >
來進行的。在Swift中可以進行操作符重載,我們會發現在String
中定義了>
的函數實現,也就是 >
本身就是一個函數 ,它接收兩個String
類型的參數 并返回一個Bool
類型的值。這和 Sort
函數的第二個參數的類型是一致的。所以,我們還可以進一步簡寫 Sort()
sort(names,>)
閉包跟函數是引用類型
無論您將函數/閉包賦值給一個常量還是變量,您實際上都是將常量/變量的值設置為對應函數/閉包的引用。這也意味著如果您將閉包賦值給了兩個不同的常量/變量,兩個值都會指向同一個閉包.