每天学一点Swift----闭包(二)

2017-05-21  本文已影响23人  冯可乐同学

七.闭包表达式

1.调用闭包(使用闭包返回值):闭包的本质是功能更加灵活的代码块,因此完全可以将闭包赋值给变量(联想函数类型的变量)或直接调用闭包。举个栗子:

//定义一个闭包,并为闭包表达式的形参定义外部形参名,然后将闭包赋值给square变量

var square = {(value val : Int) -> Int in

return val * val

}

//这里和函数赋值给一个变量的实质内容是完全一样的,只是声明的写法不相同而已,对比与函数类型的变量,这里我称为闭包类型的变量

//使用闭包变量

println(square(5))//输出25

println(square(6))//输出36

//使用闭包表达式来定义闭包,并在闭包表达式后面增加圆括号来调用该闭包

//----更加牛逼了哈,,这样能调用多次吗??--答案是:no

var result = {(#base : Int, #exponent : Int) -> Int in

var result = 1

for i in exponent

{

result *= base

}

return result

}(3, 4)//使用圆括号调用闭包,计算3的4次方,则result得到是闭包的返回值

println(result)//输出81

2.从上面的程序中还可以看出,虽然闭包表达式支持为形参指定外部形参名,但这个外部形参名没有任何作用----程序调用闭包时依然不需要外部形参名,因此使用闭包表达式定义闭包是不需要指定外部形参名

3.完整的闭包表达式需要定义形参类型、返回值类型,但是Swift可以根据闭包表达式上下文推断形参类型、返回值类型,那么闭包表达式就可以省略形参类型、返回值类型。----如果闭包表达式省略了返回值类型,那就无须书写->符号;如果闭包表达式省略了形参类型,则也可以省略形参列表的圆括号。

4.举个栗子:

//使用闭包表达式,由于程序定义了square变量的类型,因此Swift可以推断闭包表达式的形参类型、返回值类型,因此可以省略闭包表达式的形参类型、返回值类型

var square : (Int) -> Int = {(val) in return val * val}

//省略形参类型后,也可以省略形参列表的圆括号,即上面的代码可以化简如下:

var square : (Int) -> Int = {val in return val * val}

println(square(5))// 25

println(square(6))// 36

//由于调用闭包表达式传入了4,3,因此Swift可以推断出闭包表达式的两个形参都是Int类型。程序将闭包表达式的返回值赋值给Int类型的变量,因此该闭包表达式的返回值是Int类型,只要Swift可以推断出闭包表达式的形参类型、返回值类型,闭包表达式即可省略形参类型、返回值类型。

var result : Int = {base, exponent in

var result = 1

for i in 1...exponent

{

result *= base

}

return result

}(4, 3)

print(result)// 64

5.省略return:如果闭包表达式的执行体只有一行代码,而且这行的返回值作为闭包表达式的返回值,那么Swift允许省略return关键字。举个栗子:

(1)//省略形参类型,省略返回值类型

//由于该闭包表达式只有一行代码,因此可以省略return关键字

var square : (Int) -> Int = (val in val * val)

print(square(5))//输出25

(2)//由于Swift无法推断闭包表达式的形参类型、返回值类型,因此不能省略形参类型、返回值类型

//由于闭包表达式只有一行代码,因此可以省略return关键字

var cube = {(val : Int) -> Int in val * val * val}

print(cube(5))//输出125

6.省略形参名:在闭包表达式可以省略形参类型、返回值类型的情况下,Swift甚至允许省略闭包表达式的形参名。如果闭包表达式省略了形参名,in关键字也就不需要了。此时,Swift允许闭包表达式通过$0, $1, $2....名字来引用第一个、第二个、第三个...形参。举个栗子:

//省略闭包表达式的形参类型、返回值类型、return关键字、形参名

//$0代表该闭包表达式中唯一的形参

var square : Int -> Int = {$0 * $0}

print(square(5))//输出25

//省略闭包表达式的形参类型、返回值类型、形参名,但不能省略return关键字

//$0代表该闭包表达式中的第一个形参,$1代表第二个形参

var result : Int = {

var result = 1

for i in 1...$1

{

result *= $0

}

return result

}(4, 3)

print(result)//输出64

7.尾随闭包

(1)比如有这样一个函数:func myFunc(val : Int, fn : (Int) -> Int){...}

因为函数的最后一个参数是函数类型的,所以,程序调用时既可以传入一个函数作为参数,也可以传入一个闭包作为参数,----再次证明,函数类型和闭包类型的实质是相同的。

(2)如果传入闭包作为参数,那么程序的调用方式为:

myFunc(20, {doSomethinf...}) ----花括号中的内容是闭包的执行体。

(3)从上面可以看出,如果传入类闭包作为参数,那么闭包的花括号就在函数的圆括号里面。

(4)尾随闭包则是一个提高可读性的写法----如果调用函数的***最后一个***参数是闭包,那么Swift将调用函数的圆括号提到闭包表达式的花括号之前,这种用法就被称为尾随闭包。

myFunc(20){doSomething...}----花括号中的内容是闭包的执行体。

*****看着跟定义函数的格式很像,用的时候一定要看仔细啊。。。。

(5)再次举个栗子:

//定义函数类型的形参,其中fn是(Int) -> Int类型的参数

func map(var #data : [Int], #fn : (Int) -> Int) -> [Int]

{

//遍历data数组中的每个元素,并用fn函数对data[i]进行计算

//然后将计算结果作为新的数组元素

for var i=0,len=data.count; i

{

data[i] = fn(data[i])

}

return data

}

var data = {3, 4, 9, 5, 8}

//调用3次map函数

//计算数组元素平方。尾随闭包,省略了形参类型、形参名、返回值类型、return关键字

var result1 = map(data:data){$0, $0}

//计算数组元素立方。尾随闭包,省略了形参类型、形参名、返回值类型、return关键字

var result2 = map(data:data){$0, $0, $0}

//计算数组元素阶乘。尾随闭包,省略了形参类型、形参名、返回值类型,不能省略return关键字

var result3 = map(data:data){

var result = 1;

for index in 2...$0

{

result *= index

}

return result

}

以上就是尾随闭包的用法。

上一篇下一篇

猜你喜欢

热点阅读