Swift2.0语言教程之闭包
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语言教程之闭包的更多相关文章
- Swift2.0语言教程之函数嵌套调用形式
Swift2.0语言教程之函数嵌套调用形式 Swift2.0语言函数嵌套调用形式 在Swift中,在函数中还能够调用函数,从而形成嵌套调用.嵌套调用的形式往往有两种:一种是在一个函数中调用其它函数:还 ...
- Swift2.0语言教程之类的嵌套与可选链接
Swift2.0语言教程之类的嵌套与可选链接 Swift2.0语言类的嵌套 在一个类中可以嵌套一个或者多个类.它们的嵌套形式也是不同的,大致分为了两种:直接嵌套和多次嵌套.下面依次讲解这两种方式. S ...
- Swift2.0语言教程之下标脚本
Swift2.0语言教程之下标脚本 下标脚本 下标脚本是访问对象.集合或者序列的快速方式.开发者不需要调用实例特定的赋值和访问方法,就可以直接访问所需要的数值.例如在数组中,可以直接使用下标去访问或者 ...
- Swift2.0语言教程之类的方法
Swift2.0语言教程之类的方法 Swift2.0语言的方法 方法其实就是函数,只不过它被定义在了类中.在Swift中,根据被使用的方式不同,方法分为了实例方法和类型方法两种.这两种方法的定义也和O ...
- Swift2.0语言教程之类的属性
Swift2.0语言教程之类的属性 类 虽然函数可以简化代码,但是当一个程序中出现成百上千的函数和变量时,代码还是会显得很混乱.为此,人们又引入了新的类型——类.它是人们构建代码所用的一种通用.灵活的 ...
- Swift2.0语言教程之函数的返回值与函数类型
Swift2.0语言教程之函数的返回值与函数类型 Swift2.0中函数的返回值 根据是否具有返回值,函数可以分为无返回值函数和有返回值函数.以下将会对这两种函数类型进行讲解. Swift2.0中具有 ...
- Swift3.0语言教程字符串与URL的数据转换与自由转换
Swift3.0语言教程字符串与URL的数据转换与自由转换 Swift3.0语言教程字符串与URL的数据转换 Swift3.0语言教程字符串与URL的数据转换与自由转换,字符串中的字符永久保存除了可以 ...
- Swift3.0语言教程字符串与文件的数据转换
Swift3.0语言教程字符串与文件的数据转换 Swift3.0语言教程字符串与文件的数据转换,如果想要对字符串中的字符进行永久保存,可以将字符串中的字符写入到文件中.当然,开发者也可以将写入的内容进 ...
- Swift3.0语言教程字符串转换为数字值
Swift3.0语言教程字符串转换为数字值 Swift3.0语言教程字符串转换为数字值,在NSString中,开发者可以将字符串转换为数字值,通过这些数字值可以实现一些功能,如加法运算.减法运算等.数 ...
随机推荐
- php array转化为utf-8编码以便于转化为json数据
php中转化为json时,字符串或数组编码必须为utf-8编码. 在网上找到了一个方法可以比较简单的转化,在此记录: 利用var_export()和eval()方法var_export():输出或返回 ...
- QByteArray储存二进制数据(包括结构体,自定义QT对象)
因为利用QByteArray可以很方便的利用其API对内存数据进行访问和修改, 构建数据库blob字段时必不可少; 那如何向blob内写入自定义的结构体和类 //自定义person结构体 typede ...
- 使用pandas把mysql的数据导入MongoDB。
使用pandas把mysql的数据导入MongoDB. 首先说下我的需求,我需要把mysql的70万条数据导入到mongodb并去重, 同时在第二列加入一个url字段,字段的值和第三列的值一样,代码如 ...
- avalonJS-源码阅读(二)
上一篇文章讲述的avalon刷页面所用到的几个函数.这篇则是主要讲avalon对刷DOM刷出来的avalon自定义属性如何处理的. 目录[-] avalon页面处理(2) 数据结构 解析avalon标 ...
- 【转载】ajaxFileUpload 报这错jQuery.handleError is not a function
今天刚打个一个技术群,里面有人问标题上的问题,嘿,我恰好遇过,现在大家至少也在用jquery1.9以上的版本,ajaxfileupload的版本早就不更新了,大家可以下载看:地址这里,它例子里使用的J ...
- 监听 手机back键和顶部的回退
// 回退事件,监听 手机back键和顶部的回退 pushHistory(); window.addEventListener("popstate", function(e) { ...
- python图片处理(一)
在matlab中有相应的图像进行二值化处理,并且标记连通区域 L = bwlabel(BW,n) 返回一个和BW大小相同的L矩阵,包含了标记连BW中每个连通区域的类别标签,标签的值是1.2.num(连 ...
- 插入标识列identity_insert
插入标识列identity_insert 在进行数据插入时,如果插入列名包括标识列,常常会遇到以下3种提示: 一.“当 IDENTITY_INSERT 设置为 OFF 时,不能向表 'xxxxxxxx ...
- python 多线程删除MySQL表
一.需求分析 在<python 统计MySQL表信息>这篇博客中,链接如下: https://www.cnblogs.com/xiao987334176/p/9901692.html 已经 ...
- Nt函数原型头文件
//转自看雪,可以作为一个头文件使用,方便快捷 1 NTSTATUS NTAPI NtAcceptConnectPort( OUT PHANDLE PortHandle, IN PVOID PortI ...