转载请声明出处:http://blog.csdn.net/jinnchang/article/details/43268891
1、概念
闭包是一个自包含的功能模块,可以在代码中被传递和使用。
闭包可以捕获和存储其所在上下文中任意常量和变量的引用。Swift 会为你管理在捕获过程中涉及到的内存操作。
2、闭包的三种形式
- 全局函数(有函数名,不会捕获任何值)
- 嵌套函数(有函数名,可以在其封闭的函数中捕获值)
- 闭包表达式(没有名字,利用轻量级的语法在其围绕的上下文中捕获值)
// 1、全局函数实现闭包
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
func backwards(s1: String, s2: String) -> Bool {
return s1 > s2
}
var reversed = sorted(names, backwards)
// 2、嵌套函数实现闭包
func makeIncrementor(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementor() -> Int {
runningTotal += amount
return runningTotal
}
return incrementor
}
// 3、闭包表达式实现闭包
reversed = sorted(names, { (s1: String, s2: String) -> Bool in return s1 > s2 } )
3、闭包表达式
(1)语法形式
{ (parameters) -> return type in
statements
}
(2)闭包表达式的优化
- 利用上下文推断参数和返回值类型
- 单行闭包表达式可以省略 return 关键字
- 参数名简写(Swift 自动为内联闭包提供了参数名称简写功能,你可以直接通过 $0,$1,$2 等名字来引用的闭包的参数的值)
- 尾随闭包
// 1、原始方式
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
func backwards(s1: String, s2: String) -> Bool {
return s1 > s2
}
var reversed = sorted(names, backwards)
// 2、闭包表达式
reversed = sorted(names, { (s1: String, s2: String) -> Bool in return s1 > s2 } )
// 3、闭包表达式利用上下文推断参数和返回值类型
reversed = sorted(names, { s1, s2 in return s1 > s2 } )
// 4、闭包表达式单行可以省略 return
reversed = sorted(names, { s1, s2 in s1 > s2 } )
// 5、闭包表达式参数名简写
reversed = sorted(names, { $0 > $1 } )
// 6、闭包表达式运算符函数
reversed = sorted(names, >)
// 7、尾随闭包方式
reversed = sorted(names) { $0 > $1 }
注意:在最新的 Xcode 版本中运行上述代码会有部分语句识别不了">"的情况,报ambiguous use the operator 错误,这很可能是 Xcode 或者 Swift 暂时还不稳定造成,与语法本身无关。
4、尾随闭包(Trailing Closures)
如果你需要将一个很长的闭包表达式作为最后一个参数传递给函数,可以使用尾随闭包来增强函数的可读性。
尾随闭包是一个书写在函数括号之外的闭包表达式,函数支持将其作为最后一个参数调用。
注意:如果函数只有闭包表达式一个参数,当你使用尾随闭包时,你甚至可以把“()”省略掉。
let digitNames = [
0: "Zero", 1: "One", 2: "Two", 3: "Three", 4: "Four",
5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"
]
let numbers = [16, 58, 510]
let strings = numbers.map {
(var number) -> String in
var output = ""
while number > 0 {
output = digitNames[number % 10]! + output
number /= 10
}
return output
}
println(strings)
// prints "["OneSix", "FiveEight", "FiveOneZero"]"
5、捕获(Caputure)
闭包可以在其定义的上下文中捕获常量或变量。
即使定义这些常量和变量的原作用域已经不存在,闭包仍然可以在闭包函数体内引用和修改这些值。
func makeIncrementor(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementor() -> Int {
runningTotal += amount
return runningTotal
}
return incrementor
}
let incrementByTen = makeIncrementor(forIncrement: 10)
incrementByTen() // 10
incrementByTen() // 20
let incrementBySeven = makeIncrementor(forIncrement: 7)
incrementBySeven() // 7
incrementByTen() // 30
incrementor 函数并没有任何参数,但是在函数体内访问了 runningTotal 和 amount 变量。这是因为其通过捕获包含它的函数体内已经存在的 runningTotal 和 amount 变量而实现的。
由于没有修改 amount 变量,incrementor 实际上捕获并存储了该变量的一个副本,而该副本随着 incrementor 一同被存储。
然而,因为每次调用该函数的时候都会修改 runningTotal 的值,incrementor 捕获了当前 runningTotal 变量的引用,而不是仅仅复制该变量的初始值。捕获一个引用保证了当 makeIncrementor 结束时候并不会消失,也保证了当下一次执行 incrementor 函数时,runningTotal 可以继续增加。
6、闭包是引用类型
let alsoIncrementByTen = incrementByTen
alsoIncrementByTen() // 40
7、结语
文章最后更新时间:2015年1月30日08:59:28。
欲了解更细致的请参考官方文档:Closures