//: Playground - noun: a place where people can play
import UIKit
//Closures
/*
在 函数 章节中介绍的全局和嵌套函数实际上也是特殊的闭包,闭包采取如下三种形式之一:
.全局函数是一个有名字但不会捕获任何值的闭包
.嵌套函数是一个有名字并可以捕获其封闭函数域内值的闭包
.闭包表达式是一个利用轻量级语法所写的可以捕获其上下文中变量或常量值的没有名字的闭包
Swift 的闭包表达式拥有简洁的风格,并鼓励在常见场景中进行语法优化,主要优化如下:
.利用上下文推断参数和返回值类型
.单表达式闭包可以省略 return 关键字
.参数名称缩写
.Trailing 闭包语法
*/
var names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
func backwards(s1: String, s2: String) -> Bool {
return s1 > s2
}
//var reversed = sort(&names, backwards)
//var reversed = sort(&names, {(s1: String, s2: String) -> Bool in
// return s1 > s2
//})
//根据上下文推断类型
//var reversed = sort(&names, {s1, s2 in return s1 > s2})
//单行表达式闭包可以省略 return
//var reversed = sort(&names, {s1, s2 in s1 < s2})
//参数名称缩写
//Swift 自动为内联函数提供了参数名称缩写功能,您可以直接通过 $0,$1,$2 来顺序调用闭包的参数。
//var seversed = sort(&names, {$0 > $1})
//运算符函数
//var reversed = sort(&names, <)
//Trailing 闭包
//如果函数只需要闭包表达式一个参数,当您使用 trailing 闭包时,您甚至可以把 () 省略掉。
//var reversed = sort(&names){ $0 > $1}
//names
/*
下例介绍了如何在 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]
let strings = numbers.map{
(var number) -> String in
var output = ""
while number > 0 {
output += digitNames[Int(number % 10)]!
number /= 10
}
return output
}
strings
/*
闭包可以在其定义的上下文中捕获常量或变量。 即使定义这些常量和变量的原域已经不存在,闭包仍然可以在闭包函
数体内引用和修改这些值。
*/
func makeIncrementor(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementor() -> Int {
runningTotal += amount
return runningTotal
}
return incrementor
}
let incrementByTen = makeIncrementor(forIncrement: 10)
incrementByTen()
incrementByTen()
incrementByTen()
//
let incrementBySeven = makeIncrementor(forIncrement: 7)
incrementBySeven()
incrementByTen()
/*
上面的例子中,incrementBySeven 和 incrementByTen 是常量,但是这些常量指向的闭包仍然可以增加其捕获的变 量值。 这是因为函数和闭包都是引用类型。
*/