闭包
闭包¶
目录¶
闭包可以捕获和存储其所在上下文中任意常量和变量的引用。这就是所谓的闭合并包裹着这些常量和变量,俗称闭包。Swift会为你管理在捕获过程中涉及到的所有内存操作。闭包是自包含的函数代码块,可以在代码中被传递和使用。
闭包有三种形式:
- 全局函数是一个有名字但不会捕获任何值的闭包。
- 嵌套函数是一个有名字并可以捕获其封闭函数域内值的闭包。
- 闭包表达式是一个利用轻量级语法所写的可以捕获其上下文中变量和常量值的匿名闭包。
1.闭包表达式
闭包表达式是一种利用简洁语法构建内联闭包的方式。 闭包表达式提供了一些语法优化,使得撰写闭包变得简单明了。 下面闭包表达式的例子通过使用几次迭代展示了sorted函数定义和语法优化的方式。 每一次迭代都用更简洁的方式描述了相同的功能。
Swift 标准库提供了sorted函数,会根据您提供的基于输出类型排序的闭包函数将已知类型数组中的值进行排序。 一旦排序完成,函数会返回一个与原数组大小相同的新数组,该数组中包含已经正确排序的同类型元素。
下面的闭包表达式示例使用sorted函数对一个String类型的数组进行字母逆序排序,以下是初始数组值:
- 已知类型的数组
- 闭包函数,该闭包函数需要传入与数组类型相同的两个值,并返回一个布尔类型值来告诉sorted函数当排序结束后传入的第一个参数排在第二个参数前面还是后面。如果第一个参数值出现在第二个参数值前面,排序闭包函数需要返回true,反之返回false。
1.1闭包表达式语法
闭包表达式的语法
闭包表达式语法可以使用常量、变量和inout类型作为参数,不提供默认值。 也可以在参数列表的最后使用可变参数。 元组也可以作为参数和返回值。
1.2根据上下文推断类型
因为排序闭包函数是作为sorted函数的参数进行传入的,Swift可以推断其参数和返回值的类型。 sorted期望第二个参数是类型为(String, String) -> Bool的函数,因此实际上String,String和Bool类型并不需要作为闭包表达式定义中的一部分。 因为所有的类型都可以被正确推断,返回箭头 (->) 和围绕在参数周围的括号也可以被省略:
1.3单表达式闭包隐式返回
单行表达式闭包可以通过隐藏return关键字来隐式返回单行表达式的结果,如上版本的例子可以改写为:
1.4参数名称缩写
Swift 自动为内联函数提供了参数名称缩写功能,您可以直接通过\(0,\)1,$2来顺序调用闭包的参数。
如果您在闭包表达式中使用参数名称缩写,您可以在闭包参数列表中省略对其的定义,并且对应参数名称缩写的类型会通过函数类型进行推断。 in关键字也同样可以被省略,因为此时闭包表达式完全由闭包函数体构成:
1.5运算符函数
实际上还有一种更简短的方式来撰写上面例子中的闭包表达式。 Swift 的String类型定义了关于大于号 (>) 的字符串实现,其作为一个函数接受两个String类型的参数并返回Bool类型的值。 而这正好与sorted函数的第二个参数需要的函数类型相符合。 因此,您可以简单地传递一个大于号,Swift可以自动推断出您想使用大于号的字符串函数实现:
2.尾随闭包
如果您需要将一个很长的闭包表达式作为最后一个参数传递给函数,可以使用尾随闭包来增强函数的可读性。 尾随闭包是一个书写在函数括号之后的闭包表达式,函数支持将其作为最后一个参数调用。
在上例中作为sorted函数参数的字符串排序闭包可以改写为:
3.捕获值
闭包可以在其定义的上下文中捕获常量或变量。 即使定义这些常量和变量的原域已经不存在,闭包仍然可以在闭包函数体内引用和修改这些值。
4.闭包是引用类型
略