閉包是自包含的函數代碼塊,可以在代碼中傳遞和使用。閉包可以捕獲和存儲其所在的上下文中任意常量和變量的引用。
閉包表達式
{ (parameters) -> returnType in
statements
}
閉包表達式語法可以使用常量、變量和inout類型作為參數,不能提供默認值。
let names = ["Chris","Alex","Ewa","Barry","Daniel"];
func backwards(s1:String, _ s2:String) ->Bool{
return s1>s2
}
let reversed = names.sort(backwards);
這個對應得閉包寫法是:
let reversed = names.sort({(s1:String, s2:String) -> Bool in
return s1>s2})
①參數和返回類型可自動推斷
因為排序閉包函數是作為sort(_:)方法的參數傳入的,Swift 可以推斷其參數和返回值的類型。
let reversed = names.sort({(s1, s2) in
return s1>s2})
②單表達式可以忽略return關鍵詞
let reversed = names.sort({(s1, s2) in
s1>s2})
③可使用快捷參數,前綴$+數字,從0開始遞增
let reversed = names.sort({ $0>$1})
尾隨閉包
尾隨閉包是一個書寫在函數括號之后的閉包表達式,函數支持將其作為最后一個參數調用:
let reversed = names.sort(){ $0>$1}
捕獲值
閉包可以在其被定義的上下文中捕獲常量或變量。即使定義這些常量和變量的原作用域已經不存在,閉包仍然可以在閉包函數體內引用和修改這些值。
嵌套函數
func makeIncrementer(forIncrement amount:Int) -> () ->Int{
var runningTotal = 0
func increment() -> Int{ //increment 這個函數沒有參數
runningTotal += amount
return runningTotal
}
return increment
}
let amot = makeIncrementer(forIncrement: 5)
//amot =()->Int
amot() //5
單從函數來看increment函數沒有任何參數,但是其函數體被引用了runningTotal和amount。這是因為它從外圍函數捕獲了runningTotal和amount變量的引用。捕獲引用保證了runningTotal和amount變量在調用完makeIncrementer后不會消失,并且保證了在下一次執行incrementer函數時,runningTotal依舊存在。
func makeIncrementer1(forIncrement amount:Int) -> ()->Int{
var runningTotal = 0;
let increment = {()->Int in
runningTotal += amount;
return runningTotal
}
return increment
}