关闭

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

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

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. 冒泡排序算法 C++和PHP达到

    冒泡排序是小元素向前或向后的大要素.两个相邻元件之间的比较结果更.交换也这两个元件之间发生.它是最慢的排序算法. 效率最低的算法. 时间复杂度: 它是最差时间复杂度为:O(n^2),冒泡排序最好的时间 ...

  2. Git代理服务器设置和访问Github

    因为现在工作的网络环境有着非常严格的限制,.可以说,在最近的访问通过代理Github它采取了一些曲折的.也积累了一些相关经验.我们认为有必要注意什么. 符合"不要再发明轮子"宗旨, ...

  3. Gradle学习系列之一——Gradle快速入门(转)

    这是一个关于Gradle的学习系列,其中包含以下文章: Gradle快速入门 创建Task的多种方法 读懂Gradle语法 增量式构建 自定义Property 使用java Plugin 依赖管理 构 ...

  4. 聊聊并发(六)——ConcurrentLinkedQueue的实现原理分析

    1. 引言 在并发编程中我们有时候需要使用线程安全的队列.如果我们要实现一个线程安全的队列有两种实现方式:一种是使用阻塞算法,另一种是使用非阻塞算法.使用阻塞算法的队列可以用一个锁(入队和出队用同一把 ...

  5. Spring4.0MVC学习资料,ApplicationContext中的方法具体解释(三)

    做为java开源的一部分,spring框架一直排在老大的位置.Spring4.0 是 Spring 推出的一个重大版本号升级,进一步加强了 Spring 作为 Java 领域第一开源平台的地位.Spr ...

  6. LeanCloud获取最近会话列表和获取最后一条聊天记录

    最近公司有项目需要集成IM聊天功能,领导要求用LeanCloud集成,搞不出来就要背包滚蛋啊,没办法只能硬着头皮搞了. 刚拿到官方提供的demo感觉:嗯,不错.图片语音啥的都有了,但尼玛这还不够啊,还 ...

  7. Android - 数据存储 -在SQL数据库中保存数据

    对于重复的或结构化的数据,保存到数据库中是很好的选择,比如联系人信息.这里假设你对SQL数据库大体上了解然后帮助你学习Android上的SQLite数据库.在Android数据库上需要用到的API可以 ...

  8. 用友财务总帐(GL)模BI数据ETL分析

    业务需求,如下面的: 现在用友总帐一家公司BI分析案例. /* Sql Server2012使用作业设置定时任务,为了保证有一天运行时间 */ /* 意temp1表里一定要保证要有记录,否则以temp ...

  9. can&#39;t connect to mysql server on localhost &lt;10061&gt;

    需要启动MySQL服务.它可以通过两种方式来启动使用MySQL: 1.命令行模式. Win+R,进入cmd然后按Enter键.在命令行形式的输入: net start mysql56 mysql56是 ...

  10. python遗传算法实现数据拟合(转)

    python据说功能强大,触角伸到各个领域,网上搜了一下其科学计算和工程计算能力也相当强,具备各种第三方包,除了性能软肋外,其他无可指摘,甚至可以同matlab等专业工具一较高下. 从网上找了一个使用 ...