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. laravel更新某一个或几个字段

    //更新会员状态status $ary_where = array(); $ary_where[] = ['id', '=', $int_id]; $result = $this->obj_ad ...

  2. linux学习记录.4.常用命令

    帮助command --help    获取‘command‘命令的帮助 目录与文件 cd /home    进入‘home’目录 cd ..    返回上一级目录 cd       进入个人目录 c ...

  3. Dream------scala--函数定义、流程控制、异常处理

    Dream------scala--函数定义.流程控制.异常处理 一.函数的定义 1.新建工程

  4. 20155303 《Java程序设计》实验一(Java开发环境的熟悉)实验报告

    20155303 <Java程序设计>实验一(Java开发环境的熟悉)实验报告 一.实验内容及步骤 (一)使用JDK编译.运行简单的java程序 命令行下的程序开发 步骤一(新建文件夹): ...

  5. iframe测试

    iframe类似于frameset,iframe 和 frameset 都用于html页面的框架布局.(都可用于后台管理界面,iframe放于body标签内,frameset不能放在body标签) 1 ...

  6. vue表格中显示金额格式化与保存时格式化为数字并校验!

    最近项目中遇到了成本计算的,需要显示金额,保存一下,以后方便直接拿来用! 一 数字转金额格式显示 //数字转金额格式 format:function(s){ if(/[^0-9\.]/.test(s) ...

  7. nginx配置浅析

    一.nginx的介绍 nginx是由俄罗斯人开发的一款高性能的http和反向代理服务器,也可以用来作为邮件代理.相比较于其他的服务器,具有占用内存少,稳定性高等优势 二.nginx的配置 nginx的 ...

  8. Interval Minimum Number

    Given an integer array (index from 0 to n-1, where n is the size of this array), and an query list. ...

  9. 85.YCbCr与YUV的区别

    yuv色彩模型来源于rgb模型,该模型的特点是将亮度和色度分离开,从而适合于图像处理领域. YCbCr模型来源于yuv模型,应用于数字视频,ITU-R BT.601 recommendation 通过 ...

  10. C#之WinForm基础 新建一个不可编辑的comboBox

    慈心积善融学习,技术愿为有情学.善心速造多好事,前人栽树后乘凉.我今于此写经验,愿见文者得启发. 1.拉控件 2.添加可选数据 3.改变基本样式 4.效果图 C#优秀,值得学习.Winform,WPF ...