闭包是自包含的函数代码块,能够在代码中被传递和使用。Swift中的闭包与C和Objective-C中的代码块(blocks)以及其余一些编程语言中的Lambda函数比较类似。在本章中所讲的函数其实就是特殊的闭包。本节主要讲解关于闭包的基本使用。git
闭包表达式是一种利用简洁语法构建内联(内联相似与C语言中的宏定义)闭包的方式。如下这个代码是对两个字符串的比较。编程
import Foundation数组
//判断两个字符串的大小闭包
func compare(s1: String, s2: String) -> Bool {编程语言
return s1 > s2函数
}spa
let str1="Hello"orm
let str2="Swift"教程
if compare(str1, s2: str2) {开发
print("str1大于str2")
}else{
print("str1小于str2")
}
运行结果以下:
str1小于str2
在此代码中,当调用函数compare()时,会将str1和str2传递到给函数在定义时的参数s1,s2中,而后进行比较。在此代码中能够看到,在compare()函数中执行了一行代码,就是判断并返回,显的此函数至关冗长。此时就可使用闭包表达式使用代码变得更好。首先,来看一下闭包表达式(闭包函数)的语法形式。
{(参数列表)->返回值类型 in
语句
}
其中,参数能够是常量、变量和输入-输出参数,但没有默认值。开发者也能够在参数列表的最后使用可变参数。而元组也能够做为参数和返回值。关键字in表示闭包的参数和返回值类型定义已经完成,闭包函数体即将开始。
1.无参形式的闭包表达式
无参形式的闭包表达式语法形式以下:
{()->返回值类型 in
语句
}
它定义的语法形式以下:
let/var 闭包表达式常量名称/闭包表达式变量名称/=无参形式的闭包表达式
它调用的语法形式以下:
闭包表达式常量名称/闭包表达式变量名称()
【示例7-27】如下将使用闭包表达式实现字符串"aaaa"的输出。代码以下:
import Foundation
//输出字符串"aaaa"
var str={() in
print("aaaa")
}
str() //调用的调用形式
运行结果以下:
aaaa
2.具备参数的闭包表达式
具备参数的闭包表达式有两种形式一种是最经常使用的只有一个参数的闭包表达式;一种是具备多个参数的闭包表达式。如下是对这两种具备参数的闭包表达式的详细讲解。
(1)具备一个参数的闭包表达式
具备一个参数的闭包表达式的语法形式以下:
{(参数名:数据类型)->返回值类型 in
语句
}
它定义的语法形式以下:
let/var 闭包表达式常量名称/闭包表达式变量名称/=具备一个参数的闭包表达式
它的调用形式以下:
闭包表达式常量名称/闭包表达式变量名称()
【示例7-28】如下将使用闭包表达式输出指定字符串。代码以下:
import Foundation
//输出指定的字符串
var str={(str:String) in
print(str)
}
str("Hello")
运行结果以下:
Hello
(2)具备多个参数的闭包表达式
具备多个参数的闭包表达式的语法形式以下:
{(参数名1:数据类型,参数名2:数据类型,…)->返回值类型 in
语句
}
它定义的语法形式以下:
let/var 闭包表达式常量名称/闭包表达式变量名称/=具备多个参数的闭包表达式
它的调用形式以下:
闭包表达式常量名称/闭包表达式变量名称()
【示例7-29】使用闭包实现对两个任意数的求和计算,代码以下:
import Foundation
//实现求两个数的和
var reversed = {(s1: Int, s2: Int) -> Int in
var sum=s1+s2
return sum
}
print(reversed(10,20))
运行结果以下:
30
其实闭包表达式最长用在其余的函数中,并非单独的去使用它。
【示例7-30】如下代码将闭包表达式做为函数的一部分,来实如今判断在数组中是否有大于500或者40的元素。代码以下:
import Foundation
//定义函数
func copare(arr:[Int],value:Int,cb:(Num:Int,Value:Int)->Bool)->Bool{
//遍历数组
for item in arr{
//判断闭是否为真
if(cb(Num: item,Value: value)){
return true
}
}
return false
}
var array = [20,80,100,50,20]
//使用闭包判断是否在数组中有大于500的元素
var v1=copare(array,value: 500,cb: {(num:Int,value:Int)->Bool in
return num>value
})
//判断结果并输出·
if v1==true {
print("数组array中有比500大的元素")
}else{
print("数组array中没有比500大的元素")
}
//使用闭包判断是否在数组中有大于40的元素
var v2=copare(array,value: 40,cb: {(num:Int,value:Int)->Bool in
return num>value
})
//判断结果并输出
if v2==true {
print("数组array中有比40大的元素")
}else{
print("数组array中没有比40大的元素")
}
在此代码中,当调用copare()函数时,会将参数array、40以及闭包表达式传递到函数定义的参数中,在copare()函数中,遍历数组中元素的时候,又会去调用闭包表达式。运行结果以下:
数组array中没有比500大的元素
数组array中有比40大的元素
在使用闭包表达式时须要注意如下几点(如下都是以示例7-30来讲明的):
1.推断类型
copare()函数的第三个参数是闭包表达式,它的类型为(num:Int,value:Int)->Bool,因为Swift能够推断其参数和返回值的类型,因此->和围绕在参数周围的括号能够省略,如如下的代码:
var v1=copare(array,value:500,cb:{(num,value) in
return num>value
})
2.省略return
单行表达式闭包能够经过隐藏return关键字来隐式返回单行表达式的结果,能够将上面的例子进行修改:
var v1=copare(array,value:500,cb:{(num,value) in
num>value
})
3.简写参数名
Swift为内联函数提供了参数名缩写功能,开发者能够经过$0、$1、$2来顺序的调用闭包的参数。若是在闭包表达式中使用参数名称缩写,能够在闭包参数列表中省略对其的定义,而且对应参数名称缩写的类型会经过函数类型进行推断。in关键字也一样能够被省略,由于此时闭包表达式彻底由闭包函数体构成,将上面的例子进行修改:
var v1=copare(array, value:500,cb: {
$0 > $1
})
4.写在一行
当闭包的函数体部分很短时能够将其写在一行上面,如如下代码:
var v1=copare(array,value: 500,cb: {$0 > $1})
5.运算符函数
在Swift中String类型定义了关于大于号(>)的字符串实现,其做为一个函数接受两个String类型的参数并返回Bool类型的值。而这正好与以上代码sort函数的第二个参数须要的函数类型相符合。 所以,能够简单地传递一个大于号,Swift能够自动推断出您想使用大于号的字符串函数实现:
var v1=copare(array,value:500,cb:>)
在Swift 1.2中使用闭包表达式须要注意如下三点:
q 有单返回语句的闭包,如今类型检查时以单表达式闭包处理。
q 匿名的且含有非空返回类型的单表达式,如今能够用在void上下文中。
q 多表达式的闭包类型的状况,可能没法被类型推断出来。
若是开发者须要将一个很长的闭包表达式做为最后一个参数传递给函数,可使用Trailing闭包,它能够加强函数的可读性。Trailing闭包的通常形式以下:
func someFunctionThatTakesAClosure(closure: () -> ()) {
//函数主体部分
}
//如下不是使用trailing闭包进行的函数调用
someFunctionThatTakesAClosure({
//闭包主体部分
})
//如下是使用trailing闭包进行的函数调用
someFunctionThatTakesAClosure() {
//闭包主体部分
}
注意:trailing闭包是一个写在函数括号以后的闭包表达式,函数支持将其做为最后一个参数调用。示例7-30中代码也能够写为Trailing闭包,代码以下:
import Foundation
func copare(arr:[Int],value:Int,cb:(Num:Int,Value:Int)->Bool)->Bool{
for item in arr{
if(cb(Num: item,Value: value)){
return true
}
}
return false
}
var array = [20,80,100,50,20]
var v1=copare(array,value:500) {(num:Int,value:Int)->Bool in
return num>value
}
if v1==true {
print("数组array中有比500大的元素")
}else{
print("数组array中没有比500大的元素")
}
…
Trailing闭包通常使用在当闭包很长以致于不能在一行进行编写的代码中。如如下的例子就使用了Trailing闭包,实现将数字改成英文的功能。代码以下:
import Foundation
//建立字典
let digitNames = [
0: "Zero", 1: "One", 2: "Two", 3: "Three", 4: "Four",5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"
]
//建立数组
let numbers = [521,52,1,13,14]
//如下是使用trailing闭包进行的函数调用,实现将数字转为英文
let strings = numbers.map {
(var number) -> String in
var output = ""
while number > 0 {
output = digitNames[number % 10]! + output
number /= 10
}
return output
}
//遍历并输出
for index in strings{
print(index)
}
运行结果以下所示:
FiveTwoOne
FiveTwo
One
OneThree
OneFour
注意:在此代码中使用到了函数map(),它的功能是返回一个新的序列。其语法形式以下:
map(序列,闭包表达式)
其中,若是闭包表达式适用于序列中的全部元素,就会返回一个新的序列。可是在本示例中因为闭包中的内容比较多,就将它使用了Trailing闭包的形式。
闭包能够在其定义的上下文中捕获常量或变量。如下就使用incrementor()函数从上下文种对值runningTotal和amount进行捕获。代码以下:
import Foundation
func makeIncrementor(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
//定义函数incrementor(),实现runningTotal的增长
func incrementor() -> Int {
runningTotal += amount
return runningTotal
}
return incrementor
}
//赋值
var a = makeIncrementor(forIncrement: 10)
//输出
print("输出a的增量")
print(a())
print(a())
print(a())
var b = makeIncrementor(forIncrement: 5)
//赋值,输出
print("输出b的增量")
print(b())
print(b())
print(b())
运行结果以下所示:
输出a的增量
10
20
30
输出b的增量
5
10
15
本文选自:Swift2.0语言快速入门v3.0 大学霸内部资料,转载请注明出处,尊重技术尊重IT人!