关闭

封闭件是从包括以下各项的组。它可以在代码被发送“片”。。。

行,不纠结的定义。继续。

swift的闭包,有点像C和Objective-C语言里的 代码块 {……} 

闭包能够捕捉而且保存在它所被定义的那个东西的上下文中定义的常量和变量。

其实,在上一个笔记——函数,中的全局函数和嵌套函数。全都是闭包的特殊形式。

全局函数——是一个带有函数名的,并不捕捉不论什么值的函数。

嵌套函数——是一个带有函数名的而且从它被定义的外层函数中捕捉数值的函数。
闭包表达式——是一个不带函数名的,使用一种轻便的语法书写方式。而且能够从它被定义的外层函数中捕捉数值的函数。

从上面三个类型的函数的描写叙述。能够看出。事实上所谓的闭包(闭包表达式),就是一个不带函数名的嵌套函数。仅仅只是,他的书写方式有点特别罢了。


swift 的闭包,鼓舞我们把他写得短小而且希望没有废话的方式。

。。我们都懂的。这样的所谓的静止小巧短小尽量没有废话的方式,有时候会让人发狂,这正是闭包,这个玩意的难于理解之处吧!


只是,没关系。官方给的文档,足以让我们从一个让正人类能读懂的函数開始,慢慢变成一个非人正人类也可能会抓狂的函数的特殊形式——闭包。

刚才说到闭包推荐我们把函数尽量优化到所谓的短小和没有废话,那么先看一下。哪些部分会被“优化”掉:
1. 可以依据上下文推理出来的參数 以及 函数的返回值类型
2. 仅仅有一条语句构成的简单表达式的”return"keyword
3. 变量的名字
4. Trailing closure syntax (后关闭的语法: 这个东西。我没有找到适合的解释。我自己的理解它类似于只在函数的结尾才有返回的方式,也就是在不论什么一个函数体内,不论什么一个分支都不会打断函数的运行,一直到函数的最后一行的一个return或者无返回值之类的)

在swift的基本库中,有一个叫作sort的函数。它能够给Array中的元素排序。然后返回一个与传入的Array一样类型和元素个数的新的Array。

sort的原型:
sort(array: T[], pred: (T, T) -> Bool)  //这是个泛型, pred是它内部用的,不用管。总之,參数2是个函数
假设參数2是个函数,这个不理解的话,还是先回头去把函数那部分复习一遍吧

这样可能不太easy读。那么我把它变形一下:
sort(myArray: Int[],  (Int, Int) -> Bool)  //这是个Int型的处理方式
(感谢 swift技术交流第一平台(355277)的群友 packy(974871365) 指出之前写的时候,sort的右括号被我弄丢了,如今改好了 )

sort的第一个參数是个Int型数组, 第二个參数是个函数,这个函数有两个參数,返回值是Bool型
当然我们也能够把原型中的T换成其他的类型,比方:
sort(myArray: String[],  (String, String) -> Bool)
sort(myArray: Double[], (Double, Double) -> Bool)
以此类推,随便换成我们想要的形式 (泛型的意义如此)

let names = [“Chris”, “Alex”, “Ewa”, “Barry”, “Daniella”]

func myCompareFunc (s1: String, s2: String) -> Bool {   // 这个函数,跟sort的參数2 函数原型一样
     return s1 > s2
}

var reversedNames = sort(names, myCompareFunc)  //得到了一个字母序倒序的数组

到这里,应该都非常easy理解了,sort的第一个參数,是个String数组, 第二个參数是个有两个參数而且返回Bool型的函数

sort会把names数组中的元素。按着它已经写好了的算法。取出某两个下标的值,然后传入到第二个參数定义的那个函数中。而第二个參数的函数是我们写的,假设參数1> 參数2,就返回true。这里是字符串。返回的字母表中字母的顺序,b排在a后面。所以b > a是true

前面说了,闭包有点像C语言和Objective-C里面的“代码块”, 所以,闭包的形式是这种:
{                                                       //代码块開始
     (參数) -> 返回值类型 in              //注意这个语法: in 之后就是函数体了
          函数体
}                                                       //代码块结束
更前面的时候,已经说了,闭包没有函数名。。。

所以上面根本就没有函数名,但他仍然是个函数。


我们用闭包的形式,来改写上面写过的sort的调用。以及 myCompareFunc的定义:

reversedNames = sort(names,  //參数2在以下
{                                                       //代码块開始
     (s1: String, s2: String) -> Bool in     //注意这个语法: in 之后就是函数体了
          return s1 > s2                         
}                                                       //代码块结束
) // sort调用结束

这里sort的第二个參数,已经被我们替换成了上面提到的闭包的形式了
如今,我把一些换行符和一些空格以及凝视删掉。不过删换行和空格和凝视哦:

reversedNames = sort(names, {(s1:String, s2:String)->Bool in return s1 > s2} )  //对照一下,我没有多删东西吧

由于,这个闭包中的全部的參数类型(与sort的第一个參数的基本类型同样) 以及返回值类型(sort要求第二个函数的返回值类型为Bool),全都是能够判断出来的,所以,类型能够省略,于是上面的这一条调用,就变成了:

reversedNames = sort(names, {s1, s2 in return s1 > s2} )  //我仅仅删了參数类型和返回值类型

在上面的红字部分,提到,闭包中。能够省略的东西,2.仅仅有一条语句构成的简单表达式的”return”keyword, 所以,我们继续把return这个keyword也删掉, sort的调用就变成了:

reversedNames = sort(names, {s1, s2 in s1 > s1}) (感谢 swift苹果开发超级群(191026105)的群友 阿康ゞ(409767959) 指出这里第二个变量笔误 )
reversedNames = sort(names, {s1, s2 in s1 > s2})
到这里,是不是sort已经变得不太easy读了。。。

但还没完:


对于inline的闭包, swift还提供了Shorthand Argument Names。作为參数的简写,以省去參数名,  $0代表第一个參数,$1代表第二个參数, $2……. 甚至连 in 都能够省了, 于是 sort调用的新版本号:

reversedNames = sort(names, {$0 > $1})

操作符函数
上面的sort调用已经够短了,可是对于操作符 > 来说,它须要的是两个參数,而且返回值为Bool型。这正好符合了sort函数第2个參数所要求的函数形式。于是。我们能够把 > 当作函数,直接放在sort的第2个參数位置:

reversedNames = sort(names, >)          //人类已经无法阻止闭包的简化了......
关于操作符作为函数。假设并不了解操作符重载的话,确实不好理解,那么请问度娘:“操作符重载” 是什么吧

Trailing Closures
假设。闭包表达式作为函数的最后一个參数的时候,闭包表达式又非常长。不能像上面写成那么短的形式的话。那么,能够把闭包表达式,写在函数调用的外面,也就是()的后面,或者是以下:
func myCallClosure(closure: () -> ()) {          //參数是个函数,名字叫closure而已。

。。

     closure()              //用參数的名字closure, 调用传入的函数
}

myCallClosure({})          //我仅仅是放了个空闭包{}在这里
假设{}中的内容非常长。我们能够把{}放在()外面:

myCallClosure() {

}
这个看起来很像函数的定义了,但他不是。由于函数名前面没有 funckeyword。
如今。我们回来看看sort,他的函数定义。也是最后一个參数要求传入函数。所以,我们能够把刚刚的sort,变成:

reversedNames = sort(names) { $0 > $1 }    //我认为,连closure他爹都非常难一眼看出来了。。


我记得前几天,有群友,帖了这样一段代码,问:这是什么意思。今天。我才知道他一定是没有好好读手冊!!

!!!

看下他帖的代码:




通过上面闭包的学习,如今是不是非常easy看懂这个代码就是个闭包了? 仅仅只是map后面没有写()
至于这个numbers.map是怎么用的(numbers是个Array。map是Array的方法)。这段代码的具体意思,手冊上都有非常详尽的解说,我就不列在这里,也不要再问这个问题了,不要搞得好像自己学习能力非常差一样。


Capturing Values
早些时候。提到了闭包能够捕捉并保存它的外层函数的常量和变量,接下来,我们来看看,有什么奇妙的事情,假设上面的闭包内容都理解了之后。这一段,事实上没啥好说的。直接上官方代码:



incrementor是个嵌套函数, 它返回了一个Int, 可是奇妙的是。他没有传入參数,而是使用了一个叫作runningTotal的外层函数makeIncrementor定义的一个局部变量,当makeIncrementor返回incrementor函数的时候,实际上是返回了incrementor函数的一个复制出来的实体函数(每次调用makeIncrementor的时候都会复制一个新的incrementor函数),
正由于闭包能够保存它外层函数定义的常量和变量,所以,当外层函数的作用域已经不存在的时候。它依旧能够使用那个常量或变量的值:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc3VwZXJnZXJt/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast">


看到每次调用 incrementByTen(),得到的结果在递增了吧? 



这一段。也证明了我上面的猜:每次调用makeIncrementor的时候都会复制一个新的incrementor函数

闭包是引用类型



这里并没有调用 makeIncrementor去复制一个新的函数。而不过定义了一个变量 alsoIncrementByTen 被赋值成了 incrementByTen //这个函数在上面的时候,已经被调用了多次,正由于闭包是引用类型。这里的alsoIncrementByTen实际上不过 incrementByTen 引用的那个之前复制出来的函数的新引用而已。于是,得到的结果是50.


版权声明:本文博客原创文章,博客,未经同意,不得转载。

swift 笔记 (七) —— 关闭的更多相关文章

  1. (转)Qt Model/View 学习笔记 (七)——Delegate类

    Qt Model/View 学习笔记 (七) Delegate  类 概念 与MVC模式不同,model/view结构没有用于与用户交互的完全独立的组件.一般来讲, view负责把数据展示 给用户,也 ...

  2. Elasticsearch笔记七之setting,mapping,分片查询方式

    Elasticsearch笔记七之setting,mapping,分片查询方式 setting 通过setting可以更改es配置可以用来修改副本数和分片数. 1:查看,通过curl或浏览器可以看到副 ...

  3. 《MFC游戏开发》笔记七 游戏特效的实现(一):背景滚动

    本系列文章由七十一雾央编写,转载请注明出处. http://blog.csdn.net/u011371356/article/details/9344721 作者:七十一雾央 新浪微博:http:// ...

  4. Learning ROS for Robotics Programming Second Edition学习笔记(七) indigo PCL xtion pro live

    中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS forRobotics Pro ...

  5. Typescript 学习笔记七:泛型

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  6. [Swift] Swift笔记

    开始整理Swift笔记了.打算直接用Playground去写,里面自带的Markup语法和Markdown差不多,显示的效果也不差于博客.而且用Xcode看代码也方便.所以这部分内容不再在博客里记录了 ...

  7. python3.4学习笔记(七) 学习网站博客推荐

    python3.4学习笔记(七) 学习网站博客推荐 深入 Python 3http://sebug.net/paper/books/dive-into-python3/<深入 Python 3& ...

  8. Go语言学习笔记七: 函数

    Go语言学习笔记七: 函数 Go语言有函数还有方法,神奇不.这有点像python了. 函数定义 func function_name( [parameter list] ) [return_types ...

  9. iOS 学习笔记七 【博爱手把手教你使用2016年gitHub Mac客户端】

    iOS 学习笔记七 [博爱手把手教你使用gitHub客户端] 第一步:首先下载git客户端 链接:https://desktop.github.com 第二步:fork 大神的代码[这里以我的代码为例 ...

随机推荐

  1. 教你如何使用U盘装系统

    首先,你必须有一个4G以上U菜,然后,U光盘制作软件(这里我们使用url=KRVS0FUdaNAMKPUXUxjEijxBMalUjaJHph-tL-x4gXGSwVNUW3fj6RfuZtrMg1Y ...

  2. mac_Mac环境下怎样编写HTML代码?

    在Mac环境下,使用默认的文本编辑器编写的HTML的源代码, 使用不同的浏览器打开后,依旧还是显示源代码 推荐使用UltraEdit,问题就迎刃而解了

  3. ubuntu中KDE与GNOME安装切换

    转载:http://apps.hi.baidu.com/share/detail/18919303 1.在Ubuntu中安装KDE桌面命令 sudo apt-get install kUbuntu-d ...

  4. 【SICP读书笔记(三)】练习2.18 --- 表序列的reverse方法

    来自练习2.18 请定义出过程reverse,它以一个表为参数,返回的表中所包含的元素与参数表相同,但排列顺序与参数表相反: (reverse (list 1 4 9 16 25)) (25 16 9 ...

  5. 在汉澳sinox2014建立ZFS高可靠文件存储系统

    在汉澳sinox2014建立ZFS高可靠文件存储系统 汉澳sinox2014能够用比較小的固态硬盘安装,文件系统能够用zfs系统存放. 请准备一些硬盘,比方三块SCSI硬盘:da0,da1,da2 如 ...

  6. C++11:强类型枚举(enum)

    // C++11之前的enum类型是继承C的,不温不火: // C++11对enum动刀了,加强了类型检查,推出强类型enum类型,眼前一亮 // 使用过QT 的都知道,早就应该这么做了,用的非常爽! ...

  7. Stack-based buffer overflow in acdb audio driver (CVE-2013-2597)

    /* 本文章由 莫灰灰 编写,转载请注明出处. 作者:莫灰灰    邮箱: minzhenfei@163.com */ 1. 漏洞描写叙述 音频驱动acdb提供了一个ioctl的系统接口让应用层调用, ...

  8. .NET读写Excel工具Spire.Xls使用(1)入门介绍

    原文:[原创].NET读写Excel工具Spire.Xls使用(1)入门介绍 在.NET平台,操作Excel文件是一个非常常用的需求,目前比较常规的方法有以下几种: 1.Office Com组件的方式 ...

  9. C#访问Java的WebService添加SOAPHeader验证的问题

    原文:C#访问Java的WebService添加SOAPHeader验证的问题 这两天做与公司OA的接口,发现C#访问Java的WebService需要提供一个SOAP的头验证信息,但是WebServ ...

  10. 国内外MD5在线解密网站

    -http://www.cmd5.com/english.aspx (457,354,352,282) - http://www.md5crack.com - http://www.hashcheck ...