闭包( Closures)
Swift 4中的闭包类似于组织为块的自包含函数,并且像C和Objective C语言一样调用。 在函数内定义的常量和变量引用被捕获并存储在闭包中。 函数被视为闭包的特殊情况,它采用以下三种形式 -
全球职能 | 嵌套函数 | 关闭表达式 |
---|---|---|
有一个名字。 不捕获任何值 | 有一个名字。 从封闭函数中捕获值 | 未命名的Closures从相邻块中捕获值 |
Swift 4语言中的Closure表达式遵循清晰,优化和轻量级的语法风格,包括。
- 从上下文中推断参数和返回值类型。
- 单表达式闭包的隐式返回。
- 速记参数名称和
- Trailing closure syntax
语法 (Syntax)
以下是定义闭包的通用语法,该闭包接受参数并返回数据类型 -
{
(parameters) −> return type in
statements
}
以下是一个简单的例子 -
let studname = { print("Welcome to Swift Closures") }
studname()
当我们使用游乐场运行上述程序时,我们得到以下结果 -
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)
当我们使用游乐场运行上述程序时,我们得到以下结果 -
10
闭包中的表达式
嵌套函数提供了一种命名和定义代码块的便捷方式。 而不是表示整个函数声明和名称构造用于表示更短的函数。 通过闭包表达式实现在具有集中语法的清晰简短语句中表示函数。
升序订单计划
对字符串进行排序是通过Swift 4s密钥保留功能“已排序”实现的,该功能已在标准库中提供。 该函数将按升序对给定字符串进行排序,并返回具有旧数组中提到的相同大小和数据类型的新数组中的元素。 旧阵列保持不变。
在排序函数中表示两个参数 -
已知类型的值表示为数组。
数组内容(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。
闭包表达式语法使用 -
- 常数参数,
- 变量参数,和
- inout参数。
Closure表达式不支持默认值。 变量参数和元组也可以用作参数类型和返回类型。
let sum = {
(no1: Int, no2: Int) -> Int in
return no1 + no2
}
let digits = sum(10, 20)
print(digits)
当我们使用游乐场运行上述程序时,我们得到以下结果 -
30
函数语句中提到的参数和返回类型声明也可以用带有'in'关键字的内联闭包表达式函数表示。 一旦声明参数和返回类型'in'关键字用于表示闭包的主体。
单表达式隐式返回
这里,sorted函数的第二个参数的函数类型清楚地表明闭包必须返回一个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)
当我们使用游乐场运行上述程序时,我们得到以下结果 -
[75, 20, 10, 5, -6]
[-6, 5, 10, 20, 75]
语句本身清楚地定义当string1大于字符串2时返回true否则为false因此这里省略return语句。
已知类型闭包
考虑添加两个数字。 我们知道add将返回整数数据类型。 因此,已知的类型闭包被声明为 -
let sub = {
(no1: Int, no2: Int) -> Int in
return no1 - no2
}
let digits = sub(10, 20)
print(digits)
当我们使用游乐场运行上述程序时,我们得到以下结果 -
-10
将速记参数名称声明为闭包
Swift 4自动为内联闭包提供简写参数名称,可用于通过名称$ 0,$ 1,$ 2等来引用闭包参数的值。
var shorthand: (String, String) -> String
shorthand = { $1 }
print(shorthand("100", "200"))
这里,$ 0和$ 1引用闭包的第一个和第二个String参数。
当我们使用游乐场运行上述程序时,我们得到以下结果 -
200
Swift 4通过表示$ 0,$ 1,$ 2 --- $ n,便于用户将Inline闭包表示为简写参数名称。
当我们在闭包表达式中表示简写参数名称时,在定义部分中省略了闭包参数列表。 根据函数类型,将派生简写参数名称。 由于在表达式主体中定义了速记参数,因此省略了'in'关键字。
闭包作为操作符函数 (Closures as Operator Functions)
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)
当我们使用游乐场运行上述程序时,我们得到以下结果 -
[-30, -20, 18, 35, 42, 98]
关闭作为预告片
在“Trailing Closures”的帮助下声明将函数的最终参数传递给闭包表达式。 它用{}写在function()之外。 当无法在单行上内联编写函数时,需要使用它。
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)
当我们使用游乐场运行上述程序时,我们得到以下结果 -
[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()
当我们使用游乐场运行上述程序时,我们得到以下结果 -
82
64
46
当每次调用外部函数calcDecrement时,它会调用decrementer()函数并将值递减18并在外部函数calcDecrement的帮助下返回结果。 这里calcDecrement充当闭包。
即使函数decrementer()没有任何参数,默认情况下,闭包通过捕获其现有值来引用变量'overallDecrement'和'total'。 指定变量的值副本与新的decrementer()函数一起存储。 Swift 4通过在不使用变量时分配和释放内存空间来处理内存管理功能。