在 函数 章节中介绍的全局和嵌套函数实际上也是特殊的闭包,闭包採取例如以下三种形式之中的一个:
1. 全局函数是一个有名字但不会捕获不论什么值的闭包
2. 嵌套函数是一个有名字并能够捕获其封闭函数域内值的闭包
3. 闭包表达式是一个能够捕获其上下文中变量或常量值的没有名字的闭包
一、闭包表达式
闭包函数类似于Objective-C中的block。以下我们用事实说话:
let counts = [3,2,5,1,6] //********** 方法1:使用普通函数******* func sortInc(item1:Int,item2:Int) ->Bool{ return item1 < item2 } sort(counts, sortInc) //********** 方法2:使用闭包函数******* sort(counts, {(a:Int,b:Int) -> Bool in return a<b})
Swift 标准库提供了 sort 函数,会依据您提供的排序闭包将已知类型数组中的值进行排序。
方法1中使用的是普通函数,方法2传入的是一个闭包。在这里,这2个方法终于的效果是一样的。可是明显的,方法2写起来例如法1要简单
1)闭包表达式语法
{ (parameters) -> returnType in statements }
关键:闭包表达式主要分为3个部分
①闭包表达式全部内容都由大括号{}括起来
②闭包表达式keywordin前面部分和函数的定义是一样的。仅仅是去掉了func和函数名
③闭包表达式keywordin后面部分是函数的详细代码
2) 依据上下文判断类型
由于排序闭包是作为函数的參数进行传入的。Swift能够判断其參数和返回值的类型。上面的方法2中的代码能够改为以下的形式:
sort(counts,
{a,b in
return a<b})
3)单一表达式闭包能够省略 return
单一表达式闭包能够通过隐藏 return keyword来隐式返回单行表达式的结果。
上面的代码还能够省略:
sort(counts,
{a,b in a<b})
这个样例中,sort第二个參数必须返回一个Bool值,由于闭包仅仅包括一个单一表达式a<b。而且表达式返回Bool类型。所以return能够省略
4)參数名称缩写
Swift 会自己主动为内联函数提供了參数名称缩写功能。您能够直接通过 $0,$1,$2 来顺序调用闭包的參数。
假设您在闭包表达式中使用參数名称缩写。您能够在闭包參数列表中省略对其的定义,而且相应參数名称缩写的类型会通过函数类型进行判断。 in keyword也相同能够被省略。由于此时闭包表达式全然由闭包函数体构成。上面的样例能够简化成这样
sort(counts,
{$0<$1}) //$0
和 $1
表示闭包中第一个和第二个Int类型的參数。
看!Swift的闭包多洋气啊。居然能够简化成这样
5)运算符函数
实际上另一种更简单的方法。Swift中<符号能够作为一个函数来使用
sort(counts,
<)
2. Trailing 闭包
假设您须要将一个非常长的闭包表达式作为最后一个參数传递给函数。能够使用 trailing 闭包来增强函数的可读性。
Trailing 闭包是一个书写在函数括号之外(之后)的闭包表达式。函数支持将其作为最后一个參数调用。上面的样例用Trailing 闭包形式表达例如以下
sort(counts){$0<$1}
//$0
和 $1
表示闭包中第一个和第二个Int类型的參数。
注意:假设函数仅仅须要闭包表达式一个參数。当您使用 trailing 闭包时,您甚至能够把 () 省略掉。
3. 捕获 (Caputure)
闭包能够在其定义的上下文中捕获常量或变量。
即使定义这些常量和变量的原域已经不存在。闭包仍然能够在闭包函数体内引用和改动这些值。
func makeIncrementor(forIncrement amount: Int) -> () -> Int { var runningTotal = 0 func incrementor() -> Int { runningTotal += amount return runningTotal } return incrementor }
注意:
Swift 会决定捕获引用还是拷贝值。
您不须要标注 amount 或者 runningTotal 来声明在嵌入的 incrementor 函数中的使用方式。 Swift 同一时候也处理 runingTotal 变量的内存管理操作,假设不再被 incrementor 函数使用,则会被清除。
2) 闭包是引用类型
函数和闭包都是引用类型。闭包的赋值都是指针赋值。这意味着假设您将闭包赋值给了两个不同的常量/变量,两个值都会指向同一个闭包:
func makeIncrementor (forIncrement amount: Int) -> () -> Int { var runningTotal = 0 func incrementor() -> Int { runningTotal += amount return runningTotal } return incrementor } let incrementByTen = makeIncrementor(forIncrement: 10) let a = incrementByTen这里a和incrementByTen都是指针,都他们中一个的值改变,还有一个会随着一起改变
版权声明:本文博主原创文章,博客,未经同意不得转载。