本页包含内容:
- 闭包表达式(Closure Expressions)
- 尾随闭包(Trailing Closures)
- 值捕获(Capturing Values)
- 闭包是引用类型(Closures Are Reference Types)
1.闭包表达式
Swift标准库提供了sorted函数,会根据您提供的基于输出类型排序的闭包函数将已知类型数组中的值进行排序。 一旦排序完成,函数会返回一个与原数组大小相同的新数组,该数组中包含已经正确排序的同类型元素。
func sorted(array: [String],compareFunc:
(String,String)->Bool) -> [String]{
var target:[String] = array
for i in 0..<target.count{
for j in i+1..<target.count{
if compareFunc(target[i],target[j]){
let index = target[i]
target[i] = target[j]
target[j] = index
}
}
}
return target
}
let names = ["Chris","Alex","Ewa","Barry","Daniella"]
func backwards(s1: String,s2: String) -> Bool {
return s1 > s2
}
var reversed = sorted(names,backwards)
下面的例子展示了之前backwards函数对应的闭包表达式版本的代码:
reversed = sorted(names,{ (s1: String,s2: String) -> Bool in
return s1 > s2
})
//第一步简化:参数类型可以上下文推导
reversed = sorted(names,{ s1,s2 in return s1 > s2 } )
//第二步简化:只有一行的闭包可以省略return
reversed = sorted(names,s2 in s1 > s2 } )
//第三步简化:$0,$1,$2可以依次表示函数参数
reversed = sorted(names,{ $0 > $1 } )
//第四步简化:Swift的String类型定义了关于(>)的字符串实现
reversed = sorted(names,>)
如果您需要将一个很长的闭包表达式作为最后一个参数传递给函数,可以使用尾随闭包来增强函数的可读性。 尾随闭包是一个书写在函数括号之后的闭包表达式,函数支持将其作为最后一个参数调用。在上例中作为sorted函数参数的字符串排序闭包可以改写为:
reversed = sorted(names) { $0 > $1 }
下例介绍了如何在map方法中使用尾随闭包将Int类型数组[16,58,216)">510]转换为包含对应String类型的数组["OneSix","FiveEight",27)"> "FiveOneZero"]:
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
}
闭包可以在其定义的上下文中捕获常量或变量。
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
// 返回的值为20
incrementByTen()
// 返回的值为30
let incrementBySeven = makeIncrementor(forIncrement: 7)
incrementBySeven()
// 返回的值为7
// 返回的值为40
4.闭包是引用类型incrementBySeven
和incrementByTen
是常量,但是这些常量指向的闭包仍然可以增加其捕获的变量值。 这是因为函数和闭包都是引用类型。
这也意味着如果您将闭包赋值给了两个不同的常量/变量,两个值都会指向同一个闭包:
let alsoIncrementByTen = incrementByTen
alsoIncrementByTen()
// 返回的值为50