//闭包和函数是引用类型
/*闭包(类似匿名函数)三种形式
全局函数是一个有名字但不会捕获任何值的闭包
嵌套函数是一个有名字并可以捕获其封闭函数域内值的闭包
闭包表达式是一个利用轻量级语法所写的可以捕获其上下文中变量或常量值的匿名闭包
*/
let names = ["Chris","Alex", "Ewa","Barry", "Daniella"]
func backwards(s1:String, s2:String) -> Bool{
return s1 > s2
}
var reversed = names.sorted(by: backwards)
print(reversed)//["Ewa", "Daniella", "Chris", "Barry", "Alex"]
/*闭包表达式
*{(parameters)-> returnType in
* statements
* }
*/
reversed = names.sorted(by: {(s1:String, s2:String) -> Bool in
return s1 > s2
})
//写在一行
reversed = names.sorted(by: {(s1:String, s2:String) -> Bool in return s1 > s2})
//根据swift推断,返回箭头(->)和参数周围括号可以省略
reversed = names.sorted(by: {s1,s2 in return s1 > s2})
//单行表达式闭包可以通过隐藏return关键字返回表达式结果
reversed = names.sorted(by: {s1,s2 in s1 > s2})
//参数名缩写,通过$0,$1,$2顺序调用闭包的参数
//使用缩写可以省略参数定义及关键字in
reversed = names.sorted(by: {$0 > $1})
print("reversed:\(reversed)")//reversed:["Ewa", "Daniella", "Chris", "Barry", "Alex"]
//运算符函数
//大于号(>)于(String, String)-> Bool类型相符合
reversed = names.sorted(by: >)
/// 尾随闭包:是一个书写在函数括号之后的闭包表达式,函数支持将其作为最后一个参数调用。
func someFunThatTakesAClosure(Closure:() -> Void){
//函数体部分
}
// 不使用尾随闭包进行函数调用
someFunThatTakesAClosure(Closure: {
// 闭包主题部分
})
// 使用尾随闭包进行函数调用
someFunThatTakesAClosure(){
// 闭包主题部分
}
// 尾随闭包写法
reversed = names.sorted(){ $0 > $1 }
// 一个参数可以省略括号 "()"
reversed = names.sorted{ $0 > $1 }
/*捕获值
闭包可以在其定义的上下文中捕获常量或变量。即使定义这些常量和变量的原域已经不存在,
闭包仍然可以在闭包函数体内引用和修改这些值。
Swift最简单的闭包形式是嵌套函数,也就是定义在其他函数的函数体内的函数。
嵌套函数可以捕获其外部函数所有的参数以及定义的常量和量。
注意: 为了优化,Swift可能会捕捉和保存一份对值的拷贝,如果这个值是不可变或是在闭包外的。
Swift同样负责被捕捉的所有变量的内存管理,包括释放不被需要的变量。
*/
func makeIncrementor(forIncrement amount:Int) -> ()->Int
{
var runningTotal = 0
func incrementor() -> Int
{
runningTotal += amount
return runningTotal
}
return incrementor
}
let incrementByTen = makeIncrementor(forIncrement: 10)
print(incrementByTen())// 10
print(incrementByTen())// 20
print(incrementByTen())// 30
// 独立打印runningTotal变量的引用
let incrementBySeven = makeIncrementor(forIncrement: 7)
print(incrementBySeven())// 7
print(incrementByTen()) // 40
///
/*自动闭包:
被自动创建成一个包含表达式,并作为一个函数的参数进行传递,
它不需要任何参数,当它被调用的时候返回表达式内部的值
*/
var customersInline = ["Chris","Alex","Ewa","Barry","Daniella"]
print(customersInline.count)// 5
let customerProvider = {customersInline.remove(at: 0)}
print(customersInline.count)// 5
// 直到别调用数组的长度才发生个变化
print("Now serving \(customerProvider())!")// Now serving Chris!
print(customersInline.count)// 4
// 闭包作为参数传递
func serveCustomer(_ customerProvider:() -> String){
print("Now serving \(customerProvider())!") // Now serving Alex!
}
// 需要大括号"{}"
serveCustomer({customersInline.remove(at: 0)})
// 通过关键字“@autoclosure” 声明自动闭包
func serveCustomer1( customerProvider:@autoclosure() -> String){
print("Now serving \(customerProvider())!") // Now serving Ewa!
}
//不需要大括号
serveCustomer1(customerProvider: customersInline.remove(at: 0))
//自动闭包只能在函数内部调用,要在外部使用要加入关键字“escaping”
var customerProviders:[() -> String] = []
func collectCustomerProviders(customerProvider:@autoclosure @escaping () -> String){
customerProviders.append(customerProvider)
}
collectCustomerProviders(customerProvider: customersInline.remove(at: 0))
collectCustomerProviders(customerProvider: customersInline.remove(at: 0))
print("Collected\(customerProviders.count) closures.")// Collected 2 closures.
for customerProvider in customerProviders{
print("Now serving \(customerProvider())!")
}
//Now serving Barry!
//Now serving Daniella!