Swift 闭包


Swift 闭包

什么是闭包?

闭包是一种能够捕获自己作用域内部变量或常量的函数,并可以被引用和传递的一等公民。

在 Swift 中,闭包以 {} 包裹,可以在函数内部、函数外部、或作为函数参数进行使用。也因此 Swift 的闭包技术非常灵活、强大和方便。

语法格式

闭包实际上就是匿名函数,由 func 关键字、参数列表、返回类型和函数体组成。它的基本语法格式如下:

{ (parameters) -> returnType in
    statements
}

例如:

{ (x: Int, y: Int) -> Int in
    return x + y
}

说明:

  • parameters:参数列表,可以是零个或多个,支持类型推导,也可以显式指定类型。
  • returnType:返回值类型,可以是任意类型,也可以省略。
  • in:分隔符,用来分离参数列表和函数体。
  • statements:函数体,可以是一个或多个语句,可以使用外部变量或常量。

简化写法

Swift 为我们提供了一种简洁明了的写法,可以省略参数类型、返回类型和 return 关键字,称为 隐式闭包,基本语法格式如下:

{ (parameters) in
    statements
}

例如:

{ x, y in x + y }

说明:

  • 没有指定参数类型和返回类型,Swift 会根据上下文推导出类型;
  • 没有使用 return 关键字,最后一个表达式的值将作为返回值;
  • 小写字母的参数名称可以省略,用 $0$1$2 等表示参数列表中的第一个、第二个、第三个参数等。

闭包作为函数参数

Swift 闭包可以作为函数参数,用于将函数的行为作为值传递给另一个函数或方法。例如:

func calculate(a: Int, b: Int, operation: (Int, Int) -> Int) -> Int {
    return operation(a, b)
}

let result = calculate(a: 10, b: 5, operation: { $0 + $1 })
print(result)   // 15

说明:

  • operation 参数就是一个函数,它接受两个整数,并返回一个整数。
  • 我们可以把操作的方式作为闭包传递给 calculate 函数,并获得计算结果。
  • 在这个例子中,我们使用了一个隐式的闭包,它用 $0$1 表示第一个和第二个参数,然后做了加法运算。

闭包作为函数返回值

Swift 闭包也可以作为函数的返回值,用于返回动态生成的函数或方法。

例如:

func makeIncrementer(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementer() -> Int {
        runningTotal += amount
        return runningTotal
    }
    return incrementer
}

let incByTwo = makeIncrementer(forIncrement: 2)
print(incByTwo())   // 2
print(incByTwo())   // 4
print(incByTwo())   // 6

let incByTen = makeIncrementer(forIncrement: 10)
print(incByTen())   // 10
print(incByTen())   // 20

说明:

  • makeIncrementer 函数返回一个闭包,它不接受任何参数,返回一个整数。
  • incrementer 函数是内部函数,它接受一个内部变量 runningTotal 和一个参数 amount
  • 当我们调用 makeIncrementer(forIncrement: 2),得到一个闭包 incByTwo
  • 当我们调用 incByTwo(),得到一个整数,其值为 runningTotal,并将 runningTotal 加上 amount 的值(也就是 2)。
  • 当我们再次调用 incByTwo(),这时 runningTotal 就是 2,并加上 2 变成 4

尾随闭包

当闭包作为函数最后一个参数时,可以使用 尾随闭包 的方式,将大括号 {} 写在括号外面。例如:

let numbers = [1, 2, 3, 4, 5]
let mapped = numbers.map { $0 * 2 }
print(mapped)   // [2, 4, 6, 8, 10]

说明:

  • map 方法需要一个闭包作为参数,用来对数组元素进行变换。
  • 我们可以用尾随闭包的方式,将闭包写在圆括号外面,这样更加方便阅读。
  • 在这个例子中,我们使用了一个隐式的闭包,它将每个数组元素都乘以 2,并返回一个新的数组。

结语

Swift 闭包提供了非常方便和灵活的语法,可以实现一些高级的编程技巧,比如函数式编程、异步编程和响应式编程等。除了常见的高阶函数之外,我们还可以使用闭包自定义操作符、协议等,甚至可以让闭包作为一个类型的成员定义,这些用法都需要我们深入理解和掌握 Swift 闭包技术的核心概念和语法。