📜  Swift-闭包

📅  最后修改于: 2020-12-25 04:31:53             🧑  作者: Mango


Swift 4中的闭包类似于以块形式组织的自包含函数的闭包,并在诸如C和Objective C语言的任何地方调用。在函数内部定义的常量和变量引用被捕获并存储在闭包中。函数被视为闭包的特殊情况,它采取以下三种形式-

Global Functions Nested Functions Closure Expressions
Have a name. Do not capture any values Have a name. Capture values from enclosing function Unnamed Closures capture values from the adjacent blocks

Swift 4语言中的闭包表达式遵循简洁,优化和轻量级语法样式,其中包括。

  • 从上下文推断参数和返回值类型。
  • 单表达式闭包的隐式返回。
  • 速记参数名称和
  • 尾随闭包语法

句法

以下是定义闭包的通用语法,闭包接受参数并返回数据类型-

{
   (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键保留函数“ sorted”实现对字符串进行排序。该函数将按给定的字符串升序排序,并以与旧数组中提到的大小和数据类型相同的新数组返回元素。旧数组保持不变。

有两个参数表示在已排序的函数-

  • 已知类型的值表示为数组。

  • 数组内容(Int,Int),如果数组排序正确,则返回布尔值(布尔),它将返回true值,否则将返回false。

编写带有输入字符串的普通函数,并将其传递给sorted函数,以将字符串排序到新数组,如下所示-

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)

当我们使用游乐场运行上述程序时,我们得到以下结果-

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)

当我们使用游乐场运行上述程序时,我们得到以下结果-

[75, 20, 10, 5, -6]
[-6, 5, 10, 20, 75]

该语句本身清楚地定义为,当string1大于字符串2时,返回true,否则返回false,因此在此省略return语句。

已知类型的封闭

考虑两个数字的加法。我们知道加法将返回整数数据类型。因此,已知的类型闭包被声明为-

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来帮助用户将内联闭包表示为速记参数名称。

当我们在闭包表达式中表示速记参数名称时,在定义部分将省略闭包参数列表。根据函数类型,将得出速记参数名称。由于速记参数是在表达式主体中定义的,因此省略了“ 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(

当我们使用游乐场运行上述程序时,我们得到以下结果-

[-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)

当我们使用游乐场运行上述程序时,我们得到以下结果-

[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在不使用变量时通过分配和取消分配内存空间来处理内存管理功能。