参考资料与链接https://www.cnswift.org
闭包表达式
Sorted方法
let names = ["Chris","Alex","Ewa","Barry","Daniella"]
//写一个符合其类型需求的普通函数,并将它作为 sorted(by:) 方法的形式参数传入:
func backward(_ s1: String, _ s2: String) -> Bool {
return s1 > s2
}
var reversedNames = names.sorted(by: backward)
// reversedNames is equal to ["Ewa", "Daniella", "Chris", "Barry", "Alex"]
闭包表达式语法
//闭包表达式语法一般形式
{ (parameters) -> (return type) in
statements
}
- 闭包表达式语法不能提供默认值
- 可变形式参数也能使用,但需要在形式参数列表的最后面使用
- 闭包的函数整体部分由关键字 in 导入
reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
return s1 > s2
})
//可以只用一行来书写
reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in return s1 > s2 } )
从语境中推断类型
//sorted(by:) 方法期望它的第二个形式参数是一个 (String, String) -> Bool 类型的函数。
reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 } )
从单表达式闭包隐式返回
单表达式闭包能够通过从它们的声明中删掉 return 关键字来隐式返回它们单个表达式的结果
reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )
简写的实际参数名
可以通过 1 , $2 等名字来引用闭包的实际参数值
reversedNames = names.sorted(by: { $0 > $1 } )
运算符函数
reversedNames = names.sorted(by: >)
尾随闭包
reversedNames = names.sorted() { $0 > $1 }
//闭包表达式作为函数的唯一实际参数传入,而你又使用了尾随闭包的语法,那你就不需要在函数名后边写圆括号了
reversedNames = names.sorted { $0 > $1 }
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 {
(number) -> String in
var number = number
var output = ""
repeat {
output = digitNames[number % 10]! + output
number /= 10
} while number > 0
return output
}
// strings is inferred to be of type [String]
// its value is ["OneSix", "FiveEight", "FiveOneZero"]
捕获值
//有个命名为 makeIncrement 的函数栗子,其中包含了一个名叫 incrementer 一个内嵌函数。
//这个内嵌 incrementer() 函数能在它的上下文捕获两个值, runningTotal 和 amount 。
//在捕获这些值后,通过 makeIncrement 将 incrementer作为一个闭包返回,每一次调用 incrementer 时,将以 amount作为增量来增加 runningTotal
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementer() -> Int {
runningTotal += amount
return runningTotal
}
return incrementer
}
注意
如果一个值没有改变或者在闭包的外面,Swift 可能会使用这个值的拷贝而不是捕获。
闭包是引用类型
逃逸闭包
- 当闭包作为一个实际参数传递给一个函数的时候,我们就说这个闭包逃逸了,因为它可以在函数返回之后被调用。
- 当你声明一个接受闭包作为形式参数的函数时,你可以在形式参数前写 @escaping 来明确闭包是允许逃逸的。
- 让闭包 @escaping 意味着你必须在闭包中显式地引用 self.
var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
completionHandlers.append(completionHandler)
}
func someFunctionWithNonescapingClosure(closure: () -> Void) {
closure()
}
class SomeClass {
var x = 10
func doSomething() {
someFunctionWithEscapingClosure { self.x = 100 }
someFunctionWithNonescapingClosure { x = 200 }
}
}