<aside> 🦊 闭包表达式语法中的参数可以是输入输出参数,也可以是可变参数,但不能是默认参数,元组既可以作为闭包表达式语法中的参数,也可以作为返回值。
</aside>
// 函数到闭包的演化:
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
// -----> 函数:
func backward(_ s1: String, _ s2: String) -> Bool {
return s1 > s2
}
var reversedNames = names.sorted(by: backward)
// reversedNames 为 ["Ewa", "Daniella", "Chris", "Barry", "Alex"]
// -----> 闭包:
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 } )
// -----> 省略参数返回值类型闭包:
reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 } )
// -----> 单表达式隐式返回闭包:
reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )
// -----> 参数名称缩写闭包:
reversedNames = names.sorted(by: { $0 > $1 } )
// -----> 运算符方法:
reversedNames = names.sorted(by: >)
// -----> 尾随闭包:
reversedNames = names.sorted() { $0 > $1 }
// -----> 单一参数省略括号尾随闭包:
reversedNames = names.sorted { $0 > $1 }
<aside> 🏄♀️ 如果函数参数中有多个尾随闭包,只有第一个可以省略参数标签,其余的尾随闭包需写出参数标签。
</aside>
func loadPicture(from server: Server, completion: (Picture) -> Void, onFailure:() -> Void) {
if let picture = download("photo.jpg", from: server) {
completion(picture)
} else {
onFailure()
}
}
loadPicture(from: someServer) { picture in
someView.currentPicture = picture
} onFailure: {
print("Couldn't download the next picture")
}
逃逸闭包可以延迟闭包调用的时间,比如将一个闭包作为参数传递给一个函数,但是函数返回之后闭包才会被执行,这时需要指明该闭包允许“逃逸”出这个函数。
<aside>
👼 逃逸闭包中使用 self
需要显式调用,以此来检查并避免循环引用。
</aside>
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 }
}
}
let instance = SomeClass()
instance.doSomething()
print(instance.x)
// 打印出“200”
completionHandlers.first?()
print(instance.x)
// 打印出“100”
<aside>
🧝♀️ 逃逸闭包不能捕获一个指向结构体或枚举中对 self
的可变引用,因为结构体或枚举是值类型,所以被外部使用时不能为可变的。
</aside>
struct SomeStruct {
var x = 10
mutating func doSomething() {
someFunctionWithNonescapingClosure { x = 200 } // Ok
someFunctionWithEscapingClosure { x = 100 } // Error
}
}
自动闭包是一种自动创建的闭包,用于包装传递给函数作为参数的表达式。这种闭包不接受任何参数,当它被调用时,会返回被包装在其中的表达式的值。这种便利语法让你可以省略闭包的花括号,用一个普通的表达式来代替显式的闭包,且自动闭包能让你延迟求值。
var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
print(customersInLine.count)
// 打印出“5”
let customerProvider = { customersInLine.remove(at: 0) }
print(customersInLine.count)
// 打印出“5”
print("Now serving \\(customerProvider())!")
// 打印出“Now serving Chris!”
print(customersInLine.count)
// 打印出“4”