如果将一个很长的闭包表达式作为函数的最后一个实参,使用尾随闭包可以增强函数的可读性
如果闭包表达式是函数的唯一实参,而且使用了尾随闭包的语法,那就不需要在函数名后面写圆括号
示例:
var arr = [10, 1, 4, 20, 99]
// 从高到低排序
func cmp(i1: Int, i2: Int) -> Bool {
return i1 > i2
}
arr.sort(by: cmp)
arr.sort(by: {i1,i2 in i1 > i2})
arr.sort(by: {$0 > $1})
arr.sort(by: >)
arr.sort{ $0 > $1 }
print(arr)
typealias Fn = (Int) -> Int
func getFn() -> Fn {
// 局部变量
var num = 0
func plus(_ i: Int) -> Int {
num += 1
return num
}
return plus
}// 返回的plus和num形成了闭包
/* 等价于下面额写法
func getFn() -> Fn {
var num = 0
return {
num += $0
return num
}
}
*/
var fn1 = getFn() //分配了2块不同的堆空间
var fn2 = getFn()
print(fn1(1)) // 1
print(fn2(2)) // 2
print(fn1(3)) // 4
print(fn2(4)) // 6
print(fn1(5)) // 9
print(fn2(6)) // 12
class Closure {
var num = 0
func plus(_ i: Int) -> Int {
num += i
return num
}
}
var cs1 = Closure()
var cs2 = Closure()
cs1.plus(1) // 1
cs2.plus(2) // 2
cs1.plus(3) // 4
cs2.plus(4) // 6
cs1.plus(5) // 9
cs2.plus(6) // 12
typealias Fn = (Int) -> Int
var num = 11
func getFn() -> Fn {
var num = 11
func plus(_ i: Int) -> Int {
num += 1
return num
}
num = 14
return plus
} // 捕获的变量是 num = 14 如果是全局变量 则不会发生捕获
var fn1 = getFn()
fn1(1)
fn1(2)
var fn2 = getFn()
fn1(3)
fn1(4)
/////////////////////////////
typealias Fn = (Int) -> (Int, Int)
func getFns() -> (Fn, Fn) {
var num1 = 0 // 捕获的时候 分配了2份堆空间 分别alloc了1次
var num2 = 0 // alloc 分配的地址是随机的不一定连续
func plus(_ i: Int) -> (Int, Int) {
num1 += i
num2 += i << 1
return (num1, num2)
}
func minus(_ i: Int) -> (Int, Int) {
num1 -= i
num2 -= i << 1
return (num1, num2)
}
return (plus, minus)
}
let (p, m) = getFns() // 只会分配一份堆空间
print(p(6)) //(6, 12)
print(m(5)) //(1, 2)
print(p(4)) //(5, 10)
print(m(3)) //(2 , 4)
for i in 1...3 {
// func myF() -> Int {
// return i
// }
//
// functions.append(myF)
functions.append{i}
}
for f in functions {
print(f())
}
// 结果 1 2 3
// 如果第一个数大于0, 返回第一个数否则返回第二个数
func getFirstPositive(_ v1: Int, _ v2: Int) -> Int {
return v1 > 0 ? v1 : v2
}
getFirstPositive(10, 11) // 有个问题, 无论如何都会传入第二个数,即使第一个数 已经大于0了
// 改版:
func getFirstPositive1(_ v1: Int, _ v2: () -> Int) -> Int {
return v1 > 0 ? v1 : v2()
}
getFirstPositive1(10) {
print("test ----")
return 20
}
getFirstPositive1(10){20}
// 这样 10大于0 就不会调用函数了
// 但是这样调用 在简单数据时候 可读性很差
// 所以推出了 自动闭包 autoclosure
func getFirstPositive2(_ v1: Int, _ v2: @autoclosure () -> Int) -> Int {
return v1 > 0 ? v1 : v2()
}
getFirstPositive2(10, 20)
@autoclosure
会自动将20 分装成闭包表达式 {20}@autoclosure
只支持 () -> T格式的参数@autoclosure
并非只支持最后一个参数@autoclosure
技术 public func ?? <T>(optional: T?, defaultValue: @autoclosure () throws -> T) rethrows -> T
@autoclosure
修饰的 值可能会延时执行原文:https://www.cnblogs.com/yilmios/p/14671811.html