闭包
闭包表达式(Closure Expression)
swift
中可以通过func
定义一个函数, 也可以通过一个闭包表达式
定义一个函数
- 通过func的形式来实现一个函数传入两个Int参数返回两个参数之和
// 定义一个函数传入两个Int类型参数,返回这两个参数的和 func sum(_ v1: Int, _ v2: Int) -> Int { v1 + v2 } // 调用 sum(1, 2) // 3
- 通过闭包表达式的形式来实现一个函数传入两个Int参数返回两个参数之和
// 定义一个闭包表达式传入两个Int类型参数,返回这两个参数的和 var fn = { (v1: Int, v2: Int) -> Int in return v1 + v2 } // 调用 fn(10, 20)
swift
的闭包表达式
看起来跟OC
当中的block有点像,通过 in
将函数体代码和(参数列表与返回值类型)区分开来;
swift
当中的闭包表达式的格式是这样的:
{
(参数列表) -> 返回值类型 in
函数体代码
}
// 如:
{
(v1: Int, v2: Int) -> Int in
return v1 + v2
}(10, 20)
闭包表达式的简写
// 定义一个exec函数,传入两个Int类型的参数和一个函数
func exec(v1: Int, v2: Int, fn: (Int, Int) -> Int){
print(fn(v1, v2))
}
// 调用
exec(v1: 10, v2: 20, fn: {
(v1: Int, v2: Int) -> Int in
return v1 + v2
})
// 还可以这样简写
exec(v1: 10, v2: 20, fn: {
v1, v2 in return v1 + v2
})
// 这样也是可以的
exec(v1: 10, v2: 20, fn: {$0 + $1})
// 如果说前面的写法都不过分的话,那么这种写法同事看到肯定会打你的
exec(v1: 10, v2: 20, fn: +)
尾随闭包
如果将一个很长的闭包表达式
作为函数的最后一个实参
, 使用尾随闭包可以增强函数的可读性
尾随闭包
是一个被书写在函数调用括号外面(后面)的闭包表达式
func exec(v1: Int, v2: Int, fn: (Int, Int) -> Int){
print(fn(v1, v2))
}
exec(v1: 10, v2: 20, fn: {$0 + $1})
如果闭包表达式是函数的唯一实参
, 而且使用了尾随闭包的语法,那就不需要在函数名后面写圆括号
func exec(fn: (Int, Int) -> Int){
print(fn(1, 2))
}
// 调用
exec(fn: { $0 + $1 })
// 或者
exec() { $0 + $1 }
// 或者
exec { $0 + $1 }
示例:数组的排序
在swift
当中系统为我们提供了sort
函数来实现排序,调用方法如下:
var arr = [10,1,5,22,55,0]
// 使用系统提供的sort方法
arr.sort(by: {
(i1: Int, i2: Int) -> Bool in
return i1 < i2
})
arr.sort(by: {i1, i2 in return i1 < i2})
arr.sort(by: {i1, i2 in i1 < i2})
arr.sort(by: { $0 < $1 })
arr.sort(by: <)
arr.sort() { $0 < $1 }
arr.sort { $0 < $1 }
利用闭包表达式,我们可以实现自定义排序规则,比如排序一个复杂的Person等类型
/// 返回true: i1排在i2前面
/// 返回false:i1排在i2后面
func compare(i1: Int, i2: Int) -> Bool {
// 代表大的排在前面
return i1 > i2
}
arr.sort(by: compare)
闭包(Closure)
前面讲的是闭包表达式
,跟闭包
是两个不同的概念
闭包
:一个函数和它所捕获的变量\常量环境组合起来,称为闭包;一般指定义在函数内部的函数,捕获的是外层函数的局部变量\常量
// 定义一个Fn函数,接收Int参数,返回Int类型
typealias Fn = (Int) -> Int
func getFn() -> Fn {
var num = 0 // 局部变量
func plus(_ i: Int) -> Int {
num += i
return num
}
return plus
} // 返回的plus和num形成了闭包
// 调用
var fn = getFn()
print(fn(1)) // 输出1
print(fn(2)) // 输出3
print(fn(3)) // 输出6
print(fn(4)) // 输出10
正如上段代码所示,num
被getFn
函数所捕获,形成了闭包;在不停的调用getFn函数内部的fn
函数时,num会不停的进行累加。可以把闭包想象为一个类的实例对象
其本质是闭包在捕获变量之后,会通过allocObject
函数,在堆中开辟出一段空间,然后将num中的值拷贝一份到堆空间中,之后对于num的操作,都是对堆空间的值进行操作。
闭包的作用就是为了防止变量污染,内部函数拥有了外部函数的作用域
本文首次发布于 孙忠良 Blog, 作者 [@sunzhongliang] , 转载请保留原文链接.