Swift 闭包

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

{
  print("Hello World")
}

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

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


Swift 闭包声明

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

{ (parameters) -> returnType in
   // statements
}

这里,

  1. parameters - 传递给闭包的任何值
  2. returnType - 指定闭包返回值的类型
  3. in (可选) - 用于将 parameters/returnType 与闭包体分隔开

让我们看一个例子,

var greet = {
  print("Hello, World!")
}

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

要执行此闭包,我们需要调用它。调用闭包的方法如下:

// call the closure
greet()

该闭包仅打印文本 Hello World

注意:此闭包没有任何参数和返回值。


示例:Swift 闭包

// declare a closure
var greet = {
  print("Hello, World!")
}

// call the closure
greet()

输出

Hello, World!

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

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


闭包参数

与函数一样,闭包也可以接受参数。例如,

// closure that accepts one parameter
let greetUser = { (name: String)  in
    print("Hey there, \(name).")
}

// closure call
greetUser("Delilah")

输出

Hey there, Delilah.

在上面的示例中,我们将一个闭包分配给了 greetUser 变量。

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

另外,请注意闭包的调用:

greetUser("Delilah")

这里,我们将字符串值 "Delilah" 传递给了我们的闭包。

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

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


返回值的闭包

Swift 闭包可能会返回一个值,也可能不返回。如果希望闭包返回某个值,我们需要为其指定 return type 并使用 return 语句。例如,

// closure definition
var findSquare = { (num: Int) -> (Int) in
  var square = num * num
  return square
}

// closure call
var result = findSquare(3)

print("Square:",result)

输出

Square: 9

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

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

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

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

返回值存储在 result 变量中。


将闭包作为函数参数

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

// define a function
func grabLunch(search: () -> ()) {
  …
  // closure call
  search()  
}

这里,

  • search - 函数参数
  • () -> () - 表示闭包的类型
  • search() - 从函数内部调用闭包。

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

// function call
grabLunch(search: {
  print("Alfredo's Pizza: 2 miles away")
})

示例:将闭包作为函数参数

// define a function and pass closure
func grabLunch(search: ()->()) {
  print("Let's go out for lunch")

  // closure call
  search()
}

// pass closure as a parameter
grabLunch(search: {
   print("Alfredo's Pizza: 2 miles away")
})

输出

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

尾随闭包

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

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

我们可以通过将闭包作为函数体传递而无需提及参数名称来调用该函数。例如,

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

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


示例:尾随闭包

func grabLunch(message: String, search: ()->()) {
   print(message)
   search()
}

// use of trailing closure
grabLunch(message:"Let's go out for lunch")  {
  print("Alfredo's Pizza: 2 miles away")
}

输出

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

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

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

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

自动闭包

在调用函数时,我们也可以在不使用大括号 {} 的情况下传递闭包。例如,

// using {}
display(greet:{
  print("Hello World!")
}

// without using {}
display(greet: print("Hello World!"))

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

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

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


示例:自动闭包

// define a function with automatic closure
func display(greet: @autoclosure () -> ()) {
 greet()
}

// pass closure without {}
display(greet: print("Hello World!"))

输出

Hello World!

注意:我们不能向自动闭包传递参数。如果我们尝试这样做,我们会收到错误消息:“@autoclosure 参数的参数类型必须是 '()'”。

你觉得这篇文章有帮助吗?

我们的高级学习平台,凭借十多年的经验和数千条反馈创建。

以前所未有的方式学习和提高您的编程技能。

试用 Programiz PRO
  • 交互式课程
  • 证书
  • AI 帮助
  • 2000+ 挑战