「这是我参与2022首次更文挑战的第13天,活动详情查看:2022首次更文挑战」。
- 本文主要介绍Swift中闭包的定义和使用
1. 函数类型
我们开发中每天都会使用函数,函数本身也有类型,包括了形式参数和返回类型组成。
func addFunc(_ a:Int,_ b:Int) -> Int {
return a+b
}
var a = addFunc
var b = a(10,20)
这里我们函数赋值给变量后,可以通过变量进行传参执行,此时b为30.
- 我们改变类型的话
func addFunc(_ a:Int,_ b:Int) -> Int {
return a+b
}
func addFunc(_ a:Float,_ b:Float) -> Float {
return a+b
}
var a:(Float,Float)->Float = addFunc//函数名相同时,我们要指定函数的类型
var b = a(10,20)
print(b)
函数名相同时,我们要指定函数的类型,这个时候指定为Float类型后,调用的Float函数,返回值为30.0。函数也是引用类型。
2. 闭包的定义
在了解了函数了类型后,闭包是一个捕获了上下文的常量或者是变量的函数。
- 全局函数是一种特殊的闭包
func globalFunction() {
print("globalFunction")
}
定义一个全局函数,只是当前的全局函数并不捕获值
- 函数闭包
func makeIncrementer() -> () -> Int {
var runningTotal = 10
func incrementer() -> Int {
runningTotal += 1
return runningTotal
}
return incrementer
}
上面的函数是一个闭包,函数中的incrementer是一个内嵌函数,可以从makeIncrementer中捕获变量runningTotal
- 闭包表达式
{ (param) -> (returnType) in
//do something
}
闭包表达式,即一个匿名函数,而且是从上下文中捕获变量和常量。OC 中的 Block 其实是一个匿名函数,所以这个表达式要具备以下几个条件
- 作用域(也就是大括号)
- 参数和返回值
- 函数体(in)之后的代码
Swift 中的闭包即可以当做变量,也可以当做参数传递:
var closure : (Int) -> Int = { (age: Int) in
return age
}
同样的我们也可以把闭包声明成一个可选的类型:
var closure1 :(Int)->Int?
//错误的写法
closure1 = nil
//正确的写法
var closure2:((Int)->Int)?
closure2 = nil
还可以通过 let 关键字将闭包声明位一个常量(也就意味着一旦赋值之后就不能改变了)
我们也可以把闭包当作一个参数,放在函数中。
//将闭包作为函数的参数
func test(param: () -> Int){
print(param())
}
var age = 10
test { () -> Int in
age += 1
return age
}
3. 尾随闭包
当闭包作为函数的最后一个参数的时候,如果当前闭包表达式比较长的话,我们可以使用尾随闭包的方式提高代码的可读性
//闭包表达式作为函数的最后一个参数
func test(_ a: Int, _ b: Int, _ c: Int, by: (_ item1: Int, _ item2: Int, _ item3: Int) -> Bool) -> Bool{
return by(a, b, c)
}
//正常写法
test(10, 20, 30, by: {(_ item1: Int, _ item2: Int, _ item3: Int) in
return (item1 + item2)<item3
})
//尾随闭包写法
test(10, 20, 30) { (item1, item2, item3) -> Bool in
return (item1 + item2 < item3)
}
其中闭包表达式是 Swift 语法。使用闭包表达式能更简洁的传达信息。当然闭包表达式的好处 有很多:
- 1、利用上下文
推断参数和返回值类型 - 2、单表达式可以
隐式返回,即省略return关键字 - 3、参数名称的
简写,例如$0表示第一个参数 - 4、尾随闭包
表达式
看个列子
我们知道
array.sorted其实就是一个尾随闭包,且这个函数就只有一个参数。我们看下简化的过程
var array = [1,4,2]
let arr1 = array.sorted{//正常尾随闭包
(item1:Int,item2:Int) -> Bool in
return item1 > item2
}
let arr2 = array.sorted{//省略参数类型,通过上下文判断
(item1,item2) -> Bool in
return item1 > item2
}
let arr3 = array.sorted{//省略参数类型,省略返回类型,通过上下文判断
(item1,item2) in
return item1 > item2
}
let arr4 = array.sorted{//省略参数类型,省略返回类型,省略return关键字 通过上下文判断
(item1,item2) in
item1 > item2
}
let arr5 = array.sorted{// 参数名简写
return $0 > $1
}
let arr6 = array.sorted{// 参数名简写 + 省略return关键字
$0 > $1
}
let arr7 = array.sorted(by: >)//直接传比较符号
4.小结
- 闭包是一个可以
捕获上下文常量和变量的函数,闭包可以作为参数,也可以作为变量和常量进行传递。当函数中最后一个参数是闭包的话我们可以把它当作尾随闭包进行书写 - 尾随闭包可以
利用上下文推断当前参数和返回值的类型,当是单表达式的时候可以省略return,我们也可以简写参数名称使用$0,$1表示。 - 闭包是一种
引用类型,函数也是引用类型。