Swift 闭包

在本教程中,您将通过实例了解 Swift 闭包。

在 Swift 中,闭包是一种特殊类型的函数,没有函数名。例如,

  1. {
  2. print("Hello World")
  3. }

在这里,我们创建了一个打印 Hello World 的闭包。

在学习闭包之前,请确保了解 Swift 函数


Swift 闭包声明

我们不使用 func 关键字创建闭包。下面是声明闭包的语法:

  1. { (parameters) -> returnType in
  2. // statements
  3. }

在这里,

  • parameters - 传递给闭包的任何值
  • returnType - 指定闭包返回的值的类型
  • in(可选)-用于将 parameters/returnType 与封闭体分离

让我们看一个例子,

  1. var greet = {
  2. print("Hello, World!")
  3. }

在这里,我们定义了一个闭包,并将其分配给名为 greet 的变量。{} 中包含的语句是闭包体。

要执行此闭包,我们需要调用它。下面是我们如何结束。

  1. // call the closure
  2. greet()

闭包只打印文本 Hello World

注意:这个闭包没有任何参数和返回类型。

实例:闭包

  1. // declare a closure
  2. var greet = {
  3. print("Hello, World!")
  4. }
  5. // call the closure
  6. greet()

结果如下:

  1. Hello, World!

在上面的实例中,我们定义了一个闭包,并将其分配给名为 greet 的变量。

当我们调用闭包时,会执行闭包内的 print() 语句。


闭包参数

与函数类似,闭包也可以接受参数。例如,

  1. // closure that accepts one parameter
  2. let greetUser = { (name: String) in
  3. print("Hey there, \(name).")
  4. }
  5. // closure call
  6. greetUser("Delilah")

结果为:

  1. Hey there, Delilah.

在上面的实例中,我们为 greetUser 变量指定了一个闭包。

在闭包内部,(name: String) 指定闭包接受名为的 String 类型参数。请注意,我们在中使用了将闭包参数与主体分开。

另外,请注意闭包的调用

  1. greetUser("Delilah")

这里,我们向闭包传递了一个字符串值 "Delilah"。

最后,执行闭包内的语句。

注意:与函数不同,我们调用闭包时没有提到参数名。

闭包返回值

Swift 闭包可能返回值,也可能不返回值。如果我们希望闭包返回一些值,我们需要提到它的返回类型并使用 return 语句。例如,

  1. // closure definition
  2. var findSquare = { (num: Int) -> (Int) in
  3. var square = num * num
  4. return square
  5. }
  6. // closure call
  7. var result = findSquare(3)
  8. print("Square:",result)

结果如下:

  1. Square: 9

在上面的例子中,我们定义了一个返回数字平方的闭包。注意闭包定义,

  1. var findSquare = { (num: Int) -> (Int) in
  2. ...
  3. return square
  4. }

这里,(num: Int) -> (Int) 表示闭包

  • (num: Int) - 表示整数类型的参数
  • -> (Int) - 表示 Int 类型的闭包返回值
  • return square - 闭包内的 return 语句

返回的值存储在 result 变量中。


闭包作为函数参数

在 Swift 中,我们可以创建一个接受闭包作为参数的函数。

  1. // define a function
  2. func grabLunch(search: () -> ()) {
  3. // closure call
  4. search()
  5. }

这里,

  • search - 函数参数

  • () -> () - 表示闭包的类型

  • search() - 从函数内部调用闭包

现在,要调用此函数,我们需要传递一个闭包作为其参数。

  1. // function call
  2. grabLunch(search: {
  3. print("Alfredo's Pizza: 2 miles away")
  4. })
实例:闭包作为函数参数
  1. // define a function and pass closure
  2. func grabLunch(search: ()->()) {
  3. print("Let's go out for lunch")
  4. // closure call
  5. search()
  6. }
  7. // pass closure as a parameter
  8. grabLunch(search: {
  9. print("Alfredo's Pizza: 2 miles away")
  10. })

结果如下:

  1. Let's go out for food
  2. Alfredo's Pizza: 2 miles away

尾随闭包(Trailing Closure)

在尾随闭包中,如果函数接受闭包作为其最后一个参数,

  1. // function definition
  2. func grabLunch(message: String, search: ()->()) {
  3. ...
  4. }

我们可以通过将闭包作为函数体传递来调用函数,而不必使用参数的名称。例如,

  1. // calling the function
  2. grabLunch(message:"Let's go out for lunch") {
  3. // closure body
  4. }

在这里,{…} 中的所有内容都是闭包体。

实例:尾随闭包
  1. func grabLunch(message: String, search: ()->()) {
  2. print(message)
  3. search()
  4. }
  5. // use of trailing closure
  6. grabLunch(message:"Let's go out for lunch") {
  7. print("Alfredo's Pizza: 2 miles away")
  8. }

结果如下:

  1. Let's go out for lunch
  2. Alfredo's Pizza: 2 miles away

在上面的实例中,grabLunch() 函数接受闭包搜索:() -> ()。这里,闭包是函数的最后一个参数。

因此,我们通过传递闭包参数作为函数定义来调用函数。

  1. grabLunch(message:"Let's go out for lunch") {
  2. print("Alfredo's Pizza: 2 miles away")
  3. }

自动闭包

  1. // using {}
  2. display(greet:{
  3. print("Hello World!")
  4. }
  5. // without using {}
  6. display(greet: print("Hello World!"))

要在不使用大括号的情况下传递闭包参数,必须在函数定义中使用 @autoclosure 关键字。例如,

  1. func display(greet: @autoclosure () -> ()) {
  2. ...
  3. }

这里,@autoclosure 会自动添加花括号。

实例:自动闭包
  1. Hello World!

注意:我们不能向自动闭包传递参数。如果这样做,会产生错误:argument type of @autoclosure parameter must be '()'

分类导航