跳到主要内容

Swift中的闭包

提示
  1. 闭包基本概念:Swift中的闭包是无名的特殊函数类型,可通过大括号({})创建,不使用func关键字。闭包可以执行特定任务,如打印信息。
  2. 闭包参数和返回值:闭包可接受参数和返回值。声明时,参数列表写在in关键字前,返回类型在参数后,闭包体在in之后。例如,闭包可以接受一个Int类型参数并返回其平方。
  3. 闭包与函数的交互:闭包可作为函数参数,允许在调用函数时传递闭包。Swift支持尾随闭包语法,使得闭包可以更简洁地作为函数的最后一个参数传递。另外,@autoclosure关键字允许在不使用大括号的情况下传递闭包。

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

{
print("Hello World")
}

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

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

Swift 闭包声明

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

{ (参数) -> 返回类型 in
// 语句
}

这里,

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

让我们看一个示例,

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

这里,我们定义了一个闭包并将其赋值给名为 greet 的变量。{} 内封闭的语句是闭包体。

要执行这个闭包,我们需要调用它。以下是调用闭包的方法

// 调用闭包
greet()

这个闭包只是简单地打印文本 Hello World

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

示例:Swift 闭包

// 声明一个闭包
var greet = {
print("Hello, World!")
}

// 调用闭包
greet()

输出

Hello, World!

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

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

闭包参数

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

// 接受一个参数的闭包
let greetUser = { (name: String) in
print("Hey there, \(name).")
}

// 调用闭包
greetUser("Delilah")

输出

Hey there, Delilah.

在上述示例中,我们将一个闭包赋值给了 greetUser 变量。

闭包内的 (name: String) 指定了闭包接受名为 nameString 类型参数。注意我们使用了 in 来将闭包参数与体分开。

同时,注意闭包的调用

greetUser("Delilah")

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

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

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

返回值的闭包

Swift 闭包可以返回也可以不返回值。如果我们希望闭包返回某些值,我们需要指明它的返回类型并使用返回语句。例如,

// 闭包定义
var findSquare = { (num: Int) -> (Int) in
var square = num * num
return square
}

// 调用闭包
var result = findSquare(3)

print("平方:", result)

输出

平方: 9

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

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

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

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

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

闭包作为函数参数

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

// 定义一个函数
func grabLunch(search: () -> ()) {

// 调用闭包
search()
}

这里,

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

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

// 调用函数
grabLunch(search: {
print("Alfredo's Pizza: 2 miles away")
})

示例:闭包作为函数参数

// 定义一个函数并传递闭包
func grabLunch(search: ()->()) {
print("我们去吃午饭吧")

// 调用闭包
search()
}

// 将闭包作为参数传递
grabLunch(search: {
print("Alfredo's Pizza: 2 miles away")
})

输出

我们去吃午饭吧
Alfredo's Pizza: 2 miles away

尾随闭包

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

// 函数定义
func grabLunch(message: String, search: ()->()) {
...
}

我们可以在不提及参数名称的情况下,通过将闭包作为函数体传递来调用函数。例如,

// 调用函数
grabLunch(message:"我们去吃午饭吧") {
// 闭包体
}

这里,{...} 内的一切都是闭包体。

示例:尾随闭包

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

// 使用尾随闭包
grabLunch(message:"我们去吃午饭吧") {
print("Alfredo's Pizza: 2 miles away")
}

输出

我们去吃午饭吧
Alfredo's Pizza: 2 miles away

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

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

grabLunch(message:"我们去吃午饭吧")  {
print("Alfredo's Pizza: 2 miles away")
}

自动闭包

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

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

// 不使用 {}
display(greet: print("Hello World!"))

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

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

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

示例:自动闭包

// 定义一个带自动闭包的函数
func display(greet: @autoclosure () -> ()) {
greet()
}

// 不使用 {} 传递闭包
display(greet: print("Hello World!"))

输出

Hello World!

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