- 闭包
- 闭包可以捕获和存储其所在上下文中任意常量和变量的引用。这就是所谓的闭合并包裹着 这些常量和变量,俗称闭包。
- 在 函数 章节中介绍的全局和嵌套函数实际上也是特殊的闭包,闭包采取如下三种形式之 一:
-
- 全局函数是一个有名字但不会捕获任何值的闭包
-
- 嵌套函数是一个有名字并可以捕获其封闭函数域内值的闭包
-
- 闭包表达式是一个利用轻量级语法所写的可以捕获其上下文中变量或常量值的没有名字 的闭包
- 闭包主要优化如下
- 利用上下文推断参数和返回值类型
- 单表达式(single-expression)闭包可以省略 return 关键字
- 参数名称简写
- Trailing 闭包语法
*sort 函数:sort(_:)
*Swift 标准库 供了 sort 函数,会根据您 供的排序闭包将已知类型数组中的值进行排序。
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
- 排序函数有两个参数:
- 已知类型值的数组。
- 一个闭包,采用相同类型的数组的内容的两个参数,并返回一个布尔值来表示是否将第 一个值在排序时放到第二个值的前面或是后面。如果第一个值应该出现第二个值之前,闭包 需要返回 true,否则返回 false。
func backwards(s1:String, s2:String) ->Bool {
return s1 > s2
}
var reversed = names.sort(backwards)
//闭包表达式语法
reversed = names.sort({ (s1: String, s2: String) -> Bool in
return s1 > s2
})
// 在上例中作为 sort 函数参数的字符串排序闭包可以改写为:
reversed = names.sort(){ $0 > $1 }
- Trailing 闭包
- Trailing 闭包是一个书写在函数括号之外(之后)的闭包表达式,函数支持将其作为最后一个参数调用。
func someFunctionThatTakesAClosure(closure: () -> Void) {
// 函数体部分
}
// 以下是不使用 trailing 闭包进行函数调用
someFunctionThatTakesAClosure({
// 闭包主体部分
})
// 以下是使用 trailing 闭包进行函数调用
someFunctionThatTakesAClosure() {
// 闭包主体部分
}
如何在 map 方法中使用 trailing 闭包将 Int 类型数组 [16,58,510] 转换为包 含对应 String 类型的数组 [“OneSix”, “FiveEight”, “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]
现在可以通过传递一个 trailing 闭包给 numbers 的 map 方法来创建对应的字符串版 本数组。 需要注意的时调用 numbers.map 不需要在 map 后面包含任何括号,因为只需 要传递闭包表达式这一个参数,并且该闭包表达式参数通过 trailing 方式进行撰写:
let strings = numbers.map {
(number) -> String in
var number = number
var output = ""
while number > 0 {
output = digitNames[number % 10]! + output
number /= 10
}
return output
}
// strings 常量被推断为字符串类型数组,即 String[]
// 其值为 ["OneSix", "FiveEight", "FiveOneZero"]
捕获
闭包可以在其定义的上下文中捕获常量或变量。 即使定义这些常量和变量的原作用域已经 不存在,闭包仍然可以在闭包函数体内引用和修改这些值。
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementer() -> Int {
runningTotal += amount
return runningTotal
}
return incrementer
}
//makeIncrementor 返回类型为 () -> Int。 这意味着其返回的是一个函数,而不是一个简单类型值。该函数在每次调用时不接受参数只返回一个 Int 类型的值。
//使用 makeIncrementor 的例子
let incrementByTen = makeIncrementer(forIncrement: 10)
// 该例子定义了一个叫做 incrementByTen 的常量,该常量指向一个每次调用会加 10 的 incrementor函数.
incrementByTen() //10
incrementByTen() //20
incrementByTen() //30
let incrementBySeven = makeIncrementer(forIncrement: 7)
incrementBySeven() //7
incrementByTen() //40
闭包是引用类型
意味着如果您将闭包赋值给了两个不同的常量/变量,两个值都会指向同一个闭包:
let alsoIncrementByTen = incrementByTen
alsoIncrementByTen()
返回的值为50