Swift闭包Closure
所属分类:ios | 发布于 2022-12-07 09:01:32
闭包是编程语言中比较难理解的点,查阅了很多资料都没有人能给闭包下一个准确的定义。
闭包(Colsure)是词法闭包(Lexical Closure)的简称。
闭包和函数紧密相关,如果要这么问,闭包是不是一定是函数?网上没人说是,也没有人说不是,这个问题没有答案。
研究了很近,发现这么说更容易理解,闭包是一种行为,常见的嵌套函数和匿名函数是它的表现形式。在Js中,全局函数不是闭包,在Swift中,全局函数也是闭包的一种表现形式。
Swift闭包的定义
Swift闭包是自包含的代码块,可以在代码中被传递和使用。Swift中的闭包和其它编程语言中的匿名函数比较类似。
Swift闭包的三种形式
- 全局函数是一个有名字但不会捕获任何值的闭包
- 嵌套函数是一个有名字并可以捕获其封闭域内值的闭包
- 闭包表达式是一个利用轻量级语法所写的可以捕获其上下文中变量或常量值的匿名闭包。
闭包形式一:全局函数
闭包形式二:嵌套函数
闭包形式三:闭包表达式
闭包表达式是一种构建内联闭包的方式,它的语法简洁。
1、闭包表达式语法
{ (parameters) -> return type in
statements
}
使用{}来创建一个匿名闭包,使用in将参数和返回值类型的声明与闭包函数体进行分离。
闭包表达式参数可以是in-out参数,但是不能设定默认值。如果你命名了可变参数,也可以使用此可变参数。元组也可以作为参数和返回值。
简单理解为闭包表达式就是匿名函数换了种写法。
2、闭包表达式的语法迭代
Swift标准库提供了名为sorted(by:)的方法,它会基于你提供的闭包表达式的判断结果,对数组中的值(类型确定)进行排序。一旦它完成排序过程,sorted(by:)方法会返回一个与旧数组大小类型都相同的新数组,该数组有着正确的排序顺序。原数组不会被sorted(by:)方法修改。
Swift标准库中sorted(by:)的定义:
@inlinable public func sorted(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows -> [Element]
下面是初始数组:
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
2.1、写一个符合其类型要求的普通函数,将其作为sorted(by:)方法的参数传入
func backward(_ s1: String, _ s2: String) -> Bool {
return s1 > s2
}
var reversedNames = names.sorted(by: backward)
// reversedNames 为 ["Ewa", "Daniella", "Chris", "Barry", "Alex"]
如果s1大于s2,backwrad()函数返回true,表示在新的数组中s1应该出现在s2前面。
2.2、普通函数改成闭包表达式,也可以理解为改成匿名函数
reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
return s1 > s2
})
在闭包表达式中,匿名参数和返回值都写在大括号里面。
2.3、函数体部分太短,将代码改写为一行
reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in return s1 > s2 } )
2.4、根据上下文推断类型,省略类型声明
根据上下文推断类型,因为排序闭包函数作为sorted(by:)方法的参数传入的,Swift可以推断其参数和返回值的类型,sorted(by:)方法被一个字符串数组调用,因此其参数必须是(String, String) -> Bool类型的函数。这意味着(String, String)和Bool的类型声明并不需要作为闭包表达式的一部分,因为所有的类型都可以被正确推断,返回箭头和围绕在参数周围的括号也可以被省略:
reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 } )
实际上,通过内联闭包表达式构造的闭包作为参数传递给函数或方法时,总是能够推断出闭包的参数和返回值类型。这意味着闭包作为函数或者方法的参数时,你几乎不需要利用完整格式构造内联闭包。
2.5、单行表达式闭包可以通过省略return关键字来隐式返回单行表达式的结果
reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )
2.6、通过参数名称缩写功能进一步改进
Swift自动为内联闭包提供了参数名称缩写功能,你可以直接通过$0,$1,$2来顺序调用闭包的参数,以此类推。
reversedNames = names.sorted(by: { $0 > $1 } )
在这个例子中,$0和$1表示闭包中第一个和第二个String类型的参数。因为$1是编号最大的缩写参数,所以可以理解为:该闭包需要两个参数。这里的sorted(by:)函数希望得到一个参数都是字符串的闭包,因此缩写参数$0和$1的类型都是String。
2.7、最终简化版
运算符方法,Swift的String类型定义了关于大于号(>)的字符串实现,其作为一个函数接受两个String类型的参数并返回Bool类型的值。而这正好与sorted(by:)方法的参数需要的函数类型相符合。因此,你可以简单地传递一个大于号,Swift可以自动推断找到系统自带的那个字符串函数的实现:
reversedNames = names.sorted(by: >)
闭包的应用
1、利用闭包对数据进行初始化操作