- 快速教程
- 斯威夫特 - 主页
- 斯威夫特 - 概述
- Swift - 环境
- Swift - 基本语法
- Swift - 数据类型
- Swift - 变量
- Swift - 可选
- Swift - 元组
- Swift - 常量
- Swift - 文字
- Swift - 运算符
- Swift - 决策
- Swift - 循环
- Swift - 字符串
- 斯威夫特 - 角色
- Swift - 数组
- Swift - 套装
- 斯威夫特 - 字典
- Swift - 函数
- Swift - 闭包
- Swift - 枚举
- Swift - 结构
- Swift - 类
- Swift - 属性
- Swift - 方法
- Swift - 下标
- Swift - 继承
- Swift - 初始化
- Swift - 去初始化
- Swift - ARC 概述
- Swift - 可选链接
- Swift - 类型转换
- Swift - 扩展
- Swift - 协议
- Swift - 泛型
- Swift - 访问控制
- 斯威夫特有用的资源
- Swift - 在线编译
- Swift - 快速指南
- Swift - 有用的资源
- 斯威夫特 - 讨论
Swift - 闭包
Swift 4 中的闭包类似于组织为块并在任何地方调用的自包含函数,如 C 和 Objective C 语言。函数内部定义的常量和变量引用被捕获并存储在闭包中。函数被认为是闭包的特殊情况,它采用以下三种形式 -
全局功能 | 嵌套函数 | 闭包表达式 |
---|---|---|
有名字吧 不捕获任何值 | 有名字吧 从封闭函数中捕获值 | 未命名闭包捕获相邻块的值 |
Swift 4 语言中的闭包表达式遵循清晰、优化和轻量级的语法风格,其中包括。
- 从上下文推断参数和返回值类型。
- 从单表达式闭包隐式返回。
- 速记参数名称和
- 尾随闭包语法
句法
以下是定义闭包的通用语法,它接受参数并返回数据类型 -
{ (parameters) −> return type in statements }
以下是一个简单的例子 -
let studname = { print("Welcome to Swift Closures") } studname()
当我们使用 Playground 运行上述程序时,我们得到以下结果 -
Welcome to Swift Closures
以下闭包接受两个参数并返回一个 Bool 值 -
{ (Int, Int) −> Bool in Statement1 Statement 2 --- Statement n }
以下是一个简单的例子 -
let divide = { (val1: Int, val2: Int) -> Int in return val1 / val2 } let result = divide(200, 20) print (result)
当我们使用 Playground 运行上述程序时,我们得到以下结果 -
10
闭包中的表达式
嵌套函数提供了一种命名和定义代码块的便捷方法。名称结构不是用来表示整个函数声明,而是用来表示较短的函数。通过闭包表达式可以用清晰的简短语句和重点语法来表示函数。
升序程序
对字符串进行排序是通过标准库中已经提供的 Swift 4s 关键保留函数“sorted”来实现的。该函数将按升序对给定字符串进行排序,并返回新数组中的元素,其大小和数据类型与旧数组中提到的相同。旧数组保持不变。
排序函数内部表示两个参数 -
已知类型的值表示为数组。
数组内容(Int,Int)并返回布尔值(Bool),如果数组排序正确则返回 true 值,否则返回 false。
编写带有输入字符串的普通函数并将其传递给排序函数,以使字符串排序到新数组,如下所示 -
func ascend(s1: String, s2: String) -> Bool { return s1 > s2 } let stringcmp = ascend(s1: "Swift 4", s2: "great") print (stringcmp)
当我们使用游乐场运行上述程序时,我们得到以下结果 -
true
要为冰淇淋排序的初始数组给出为“Swift 4”和“great”。对数组进行排序的函数被声明为字符串数据类型,其返回类型被称为布尔值。对两个字符串进行比较并按升序排序并存储在新数组中。如果排序成功,该函数将返回 true 值,否则返回 false。
闭包表达式语法使用 -
- 常数参数,
- 可变参数,以及
- 输入输出参数。
闭包表达式不支持默认值。可变参数和元组也可以用作参数类型和返回类型。
let sum = { (no1: Int, no2: Int) -> Int in return no1 + no2 } let digits = sum(10, 20) print(digits)
当我们使用 Playground 运行上述程序时,我们得到以下结果 -
30
函数语句中提到的参数和返回类型声明也可以用带有“in”关键字的内联闭包表达式函数来表示。一旦声明了参数和返回类型,'in'关键字就被用来表示闭包的主体。
单一表达式隐式返回
在这里,排序函数的第二个参数的函数类型清楚地表明闭包必须返回 Bool 值。因为闭包的主体包含一个返回 Bool 值的表达式 (s1 > s2),所以不存在歧义,并且可以省略 return 关键字。
要在表达式闭包中返回单个表达式语句,在其声明部分中省略了“return”关键字。
var count:[Int] = [5, 10, -6, 75, 20] let descending = count.sorted(by: { n1, n2 in n1 > n2 }) let ascending = count.sorted(by: { n1, n2 in n1 < n2 }) print(descending) print(ascending)
当我们使用 Playground 运行上述程序时,我们得到以下结果 -
[75, 20, 10, 5, -6] [-6, 5, 10, 20, 75]
该语句本身明确定义了当 string1 大于 string 2 时返回 true,否则返回 false,因此这里省略了 return 语句。
已知类型的封闭件
考虑两个数字相加。我们知道加法将返回整数数据类型。因此已知的类型闭包被声明为 -
let sub = { (no1: Int, no2: Int) -> Int in return no1 - no2 } let digits = sub(10, 20) print(digits)
当我们使用 Playground 运行上述程序时,我们得到以下结果 -
-10
将简写参数名称声明为闭包
Swift 4 自动为内联闭包提供简写参数名称,可用于通过名称 $0、$1、$2 等引用闭包参数的值。
var shorthand: (String, String) -> String shorthand = { $1 } print(shorthand("100", "200"))
这里,$0 和 $1 指的是闭包的第一个和第二个字符串参数。
当我们使用 Playground 运行上述程序时,我们得到以下结果 -
200
Swift 4 方便用户通过表示 $0、$1、$2 --- $n 将内联闭包表示为简写参数名称。
当我们在闭包表达式中表示简写参数名称时,定义部分中会省略闭包参数列表。根据函数类型,将派生出简写参数名称。由于简写参数是在表达式主体中定义的,因此省略了“in”关键字。
闭包作为运算符函数
Swift 4 提供了一种简单的方法来访问成员,只需提供运算符函数作为闭包。在前面的示例中,关键字“Bool”用于在字符串相等时返回“true”,否则返回“false”。
闭包中的运算符函数使表达式变得更加简单:
let numb = [98, -20, -30, 42, 18, 35] var sortedNumbers = numb.sorted ({ (left: Int, right: Int) -> Bool in return left < right }) let asc = numb.sorted(<) print(asc)
当我们使用 Playground 运行上述程序时,我们得到以下结果 -
[-30, -20, 18, 35, 42, 98]
关闭作为预告片
将函数的最终参数传递给闭包表达式是在“尾随闭包”的帮助下声明的。用{}写在函数()外面。当无法将函数内联编写在一行上时,需要使用它。
reversed = sorted(names) { $0 > $1}
其中 {$0 > $1} 表示为在(名称)外部声明的尾随闭包。
import Foundation var letters = ["North", "East", "West", "South"] let twoletters = letters.map({ (state: String) -> String in return state.substringToIndex(advance(state.startIndex, 2)).uppercaseString }) let stletters = letters.map() { $0.substringToIndex(advance($0.startIndex, 2)).uppercaseString } print(stletters)
当我们使用 Playground 运行上述程序时,我们得到以下结果 -
[NO, EA, WE, SO]
捕获值和引用类型
在 Swift 4 中,捕获常量和变量值是在闭包的帮助下完成的。它进一步引用和修改闭包体内这些常量和变量的值,即使这些变量不再存在。
通过在其他函数体内编写函数,使用嵌套函数来捕获常量和变量值。
嵌套函数捕获 -
- 外部函数参数。
- 捕获外部函数中定义的常量和变量。
在 Swift 4 中,当在函数内声明常量或变量时,闭包也会自动创建对该变量的引用。它还提供了将两个以上变量引用为同一个闭包的功能,如下所示 -
let decrem = calcDecrement(forDecrement: 18) decrem()
这里oneDecrement和 Decrement 变量都将指向与闭包引用相同的内存块。
func calcDecrement(forDecrement total: Int) -> () -> Int { var overallDecrement = 100 func decrementer() -> Int { overallDecrement -= total print(overallDecrement) return overallDecrement } return decrementer } let decrem = calcDecrement(forDecrement: 18) decrem() decrem() decrem()
当我们使用 Playground 运行上述程序时,我们得到以下结果 -
82 64 46
每次调用外部函数 calcDecrement 时,它都会调用 decrementer() 函数并将值递减 18,并在外部函数 calcDecrement 的帮助下返回结果。这里 calcDecrement 充当闭包。
即使函数 decrementer() 没有任何参数,默认情况下闭包也会通过捕获其现有值来引用变量“overallDecrement”和“total”。指定变量值的副本使用新的 decrementer() 函数存储。Swift 4 通过在变量不使用时分配和释放内存空间来处理内存管理功能。