Swift2.0语言教程之闭包
Swift2.0语言闭包
闭包是自包括的函数代码块。能够在代码中被传递和使用。
Swift中的闭包与C和Objective-C中的代码块(blocks)以及其它一些编程语言中的Lambda函数比較相似。在本章中所讲的函数事实上就是特殊的闭包。本节主要解说关于闭包的基本使用。
Swift2.0语言闭包表达式
闭包表达式是一种利用简洁语法构建内联(内联类似与C语言中的宏定义)闭包的方式。下面这个代码是对两个字符串的比較。
-
import Foundation
-
//推断两个字符串的大小
-
func compare(s1: String, s2: String) -> Bool {
-
return s1 > s2
-
}
-
let str1="Hello"
-
let str2="Swift"
-
if compare(str1, s2: str2) {
-
print("str1大于str2")
-
}else{
-
print("str1小于str2")
-
}
执行结果例如以下:
-
str1小于str2
在此代码中,当调用函数compare()时,会将str1和str2传递到给函数在定义时的參数s1,s2中,然后进行比較。在此代码中能够看到,在compare()函数中运行了一行代码,就是推断并返回。显的此函数相当冗长。此时就能够使用闭包表达式使用代码变得更好。首先,来看一下闭包表达式(闭包函数)的语法形式。
-
{(參数列表)->返回值类型 in
-
语句
-
}
当中,參数能够是常量、变量和输入-输出參数。但没有默认值。开发人员也能够在參数列表的最后使用可变參数。
而元组也能够作为參数和返回值。
keywordin表示闭包的參数和返回值类型定义已经完毕。闭包函数体即将開始。
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大的元素
Swift2.0语言使用闭包表达式的注意事项
在使用闭包表达式时须要注意下面几点(下面都是以演示样例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
单行表达式闭包能够通过隐藏returnkeyword来隐式返回单行表达式的结果,能够将上面的样例进行改动:
-
var v1=copare(array,value:500,cb:{(num,value) in
-
num>value
-
})
3.简写參数名
Swift为内联函数提供了參数名缩写功能,开发人员能够通过$0、$1、$2来顺序的调用闭包的參数。假设在闭包表达式中使用參数名称缩写,能够在闭包參数列表中省略对其的定义。而且相应參数名称缩写的类型会通过函数类型进行判断。inkeyword也相同能够被省略。由于此时闭包表达式全然由闭包函数体构成,将上面的样例进行改动:
-
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 多表达式的闭包类型的情况,可能无法被类型判断出来。
Swift2.0语言Trailing闭包
假设开发人员须要将一个非常长的闭包表达式作为最后一个參数传递给函数,能够使用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闭包的形式。
Swift2.0语言捕获值
闭包能够在其定义的上下文中捕获常量或变量。下面就使用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人!