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
  • 语句
  • }

其中,参数可以是常量、变量和输入-输出参数,但没有默认值。开发者也可以在参数列表的最后使用可变参数。而元组也可以作为参数和返回值。关键字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大的元素

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

单行表达式闭包可以通过隐藏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  多表达式的闭包类型的情况,可能无法被类型推断出来。

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人!

Swift2.0语言教程之闭包的更多相关文章

  1. Swift2.0语言教程之函数嵌套调用形式

    Swift2.0语言教程之函数嵌套调用形式 Swift2.0语言函数嵌套调用形式 在Swift中,在函数中还能够调用函数,从而形成嵌套调用.嵌套调用的形式往往有两种:一种是在一个函数中调用其它函数:还 ...

  2. Swift2.0语言教程之类的嵌套与可选链接

    Swift2.0语言教程之类的嵌套与可选链接 Swift2.0语言类的嵌套 在一个类中可以嵌套一个或者多个类.它们的嵌套形式也是不同的,大致分为了两种:直接嵌套和多次嵌套.下面依次讲解这两种方式. S ...

  3. Swift2.0语言教程之下标脚本

    Swift2.0语言教程之下标脚本 下标脚本 下标脚本是访问对象.集合或者序列的快速方式.开发者不需要调用实例特定的赋值和访问方法,就可以直接访问所需要的数值.例如在数组中,可以直接使用下标去访问或者 ...

  4. Swift2.0语言教程之类的方法

    Swift2.0语言教程之类的方法 Swift2.0语言的方法 方法其实就是函数,只不过它被定义在了类中.在Swift中,根据被使用的方式不同,方法分为了实例方法和类型方法两种.这两种方法的定义也和O ...

  5. Swift2.0语言教程之类的属性

    Swift2.0语言教程之类的属性 类 虽然函数可以简化代码,但是当一个程序中出现成百上千的函数和变量时,代码还是会显得很混乱.为此,人们又引入了新的类型——类.它是人们构建代码所用的一种通用.灵活的 ...

  6. Swift2.0语言教程之函数的返回值与函数类型

    Swift2.0语言教程之函数的返回值与函数类型 Swift2.0中函数的返回值 根据是否具有返回值,函数可以分为无返回值函数和有返回值函数.以下将会对这两种函数类型进行讲解. Swift2.0中具有 ...

  7. Swift3.0语言教程字符串与URL的数据转换与自由转换

    Swift3.0语言教程字符串与URL的数据转换与自由转换 Swift3.0语言教程字符串与URL的数据转换 Swift3.0语言教程字符串与URL的数据转换与自由转换,字符串中的字符永久保存除了可以 ...

  8. Swift3.0语言教程字符串与文件的数据转换

    Swift3.0语言教程字符串与文件的数据转换 Swift3.0语言教程字符串与文件的数据转换,如果想要对字符串中的字符进行永久保存,可以将字符串中的字符写入到文件中.当然,开发者也可以将写入的内容进 ...

  9. Swift3.0语言教程字符串转换为数字值

    Swift3.0语言教程字符串转换为数字值 Swift3.0语言教程字符串转换为数字值,在NSString中,开发者可以将字符串转换为数字值,通过这些数字值可以实现一些功能,如加法运算.减法运算等.数 ...

随机推荐

  1. 【转】 jquery easyui datagrid使用,分页、排序、查询

    $('#dg').datagrid({ url: "xxx.ashx",                    pagination: true,                p ...

  2. 【leetcode 简单】 第七十六题 移动零

    给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序. 示例: 输入: [0,1,0,3,12] 输出: [1,3,12,0,0] 说明: 必须在原数组上操作, ...

  3. 如何开启一个Django项目

    一:新建的Django工程 新建了一个Django工程后,工程会自动创建有两个templates文件夹和unitled文件夹,再加上一个manage.py文件. 二:Django开发的一般流程 在工程 ...

  4. python3学习笔记.5.打包发布

    为了给别人使用将 .py 文件打包成 .exe 文件 安装 PyInstaller  ,完成 打开 Cmd 调用 path:\pyinstaller.exe -F path:\name.py 发布文件 ...

  5. ES6简单总结

    1.变量声明let和const 我们都是知道在ES6以前,var关键字声明变量.无论声明在何处,都会被视为声明在函数的最顶部(不在函数内即在全局作用域的最顶部).这就是函数变量提升例如: functi ...

  6. 【LinuxC】GCC编译C程序,关闭随机基址

    1.编译.链接和运行程序 C代码示例: #include <stdio.h> #include <stdlib.h> int main() { printf("hel ...

  7. Jenkins关联GitHub进行构建

    一.创建一个自由风格的项目 并在高级中勾选你构建完成后保存项目的路径 二.配置你存放代码的GitHub的地址并添加用户名密码 三.立即构建

  8. 十、springboot之web开发打包生产

    打成war包 打成war包一般可以分两种方式来实现,第一种可以通过eclipse这种开发工具来导出war包,另外一种是使用命令来完成,这里主要介绍后一种 1.修改配置文件 maven:pom文件 &l ...

  9. go语言 documentation

    Documentation文档   The Go programming language is an open source project to make programmers more pro ...

  10. 栈应用之 括号匹配问题(Python 版)

    栈应用之 括号匹配问题(Python 版) 检查括号是否闭合 循序扫描被检查正文(一个字符)里的一个个字符 检查中跳过无关字符(所有非括号字符都与当前处理无关) 遇到开括号将其压入栈 遇到闭括号时弹出 ...