swift中的闭包

swift中的闭包

闭包是自包含的函数代码块,可以在代码中被传递和使用。swift中的闭包与C和Objective-C中的代码块(blocks)以及其他一些编程语言中的匿名函数比较相似。

闭包可以捕获和存储其所在的上下文中任意常量和变量的引用。被称为包裹常量和变量。Swift会管理在捕获过程中涉及到的所有内存操作。

闭包采取如下三种形式之一:

  1. 全局函数是一个有名字但不会捕获任何值的闭包
  2. 嵌套函数是一个有名字并可以捕获其封闭函数域内值的闭包。
  3. 闭包表达式是一个利用轻量级语法缩写的可以捕获其上下文中变量或者常量值的匿名闭包

Swift的闭包表达式拥有简洁的风格,其特点如下

  1. 利用上下文推断函数和返回值类型
  2. 隐式返回单表达式闭包,即单表达式闭包可以省略 return 关键字
  3. 参数名称缩写
  4. 尾随闭包语法

嵌套函数是一个在较复杂函数中方便进行命名和定义自包含代码块的方式。当然,有时候编写小巧的没有完整定义和命名的类函数结构也是很有用处的,尤其是在处理一些函数并需要将另外一些函数作为该函数的参数时。

闭包表达式是一种利用简洁语法构建内联闭包的方式。闭包表达式提供了一些语法优化,使得撰写闭包变得简单明了。下面闭包表达式的例子通过使用几次迭代展示了sorted(by:)方法定义和语法优化的方式。每一次迭代都用更简洁的方式描述了相同的功能。

sorted 方法

swift标准库提供了名为 sorted(by:)的方法,它会根据所提供的用于排序的闭包函数将已知类型数组中的值进行排序。一旦排序完成,sorted(by:)方法会返回一个与原数组大小相同,包含同类型元素且元素已正确排序的新数组。原数组不会被 sorted(by:)方法修改。
sorted(by:)方法接受一个闭包,该闭包函数需要传入与数组元素类型相同的两个值,并返回一个布尔类型值来表明排序结束后传入的第一个参数排在第二个参数前面还是后面。如果第一个参数值出现在第二个参数值前面,排序闭包函数需要返回true,反之返回false。

提供排序闭包函数的一种方式是撰写一个符合其类型要求的普通函数,并将其作为sorted(by:)方法的参数传入:

func backward(_ s1:String,_s2:String)->Bool) { return s1>s2 }

闭包表达式语法构建内联排序闭包

闭包表达式语法有如下的一般形式

{(parameters)-> returnType in
statements
}

闭包表达式参数可以是 in-out 参数,但不能设定默认值。也可以使用具名的可变参数。元组也可以作为参数和返回值。

下面的例子展示了之前 backward(::)函数对应的闭包表达式版本的代码:

reverseNames = names.sorted(by:{s1:String,s2:String}->Bool in)
return s1>s2
})

需要注意的是内联闭包参数和返回值类型声明与backward(::)函数类型声明相同。在这两种方式中,都可写成了(s1:String,s2:String)->Bool 然而在内联闭包表达式中,函数和返回值类型都写在大括号内,而不是大括号外。

闭包的函数体部分由关键字in 引入。该关键字表示闭包的参数和返回值类型定义已经完成,闭包函数体即将开始。

由于这个闭包的函数体部分如此短,以至于可以将其改写成一行代码:

reversedNames = names.sorted(by:{(s1:String,s2:String)->Bool in return s1>s2})

该例中sorted(by:)方法的整体调用保持不变,一对圆括号仍然包裹住了方法的整个参数。然而参数现在变成了内联闭包。

根据上下文推断类型

因为排序闭包函数时作为sorted(by:)方法的参数传入的,swift可以推断其参数和返回值的类型.sorted(by:)方法被一个字符串数组调用,因此其参数必须是(String,String)->Bool 类型的函数。这意味着(String,string)和 Bool 类型并不需要作为闭包表达式定义的一部分。因为所有的类型都可以被准确推断,返回箭头和围绕在参数周围的括号也可以省略:

reversedNames = names.sorted(by:{s1,s2 in return s1>s2})

通过内联闭包表达式构造的闭包作为参数传递给函数或者方法时,总是能够推断出闭包的参数和返回值类型。这意味着闭包作为函数或者方法的参数时,几乎不需要利用完整格式构造内联闭包。
但是如果完整格式的闭包可以提高代码的可读性,我们更应该使用完整格式的闭包。而在sorted(by:)方法这个例子里,显然闭包的目的就是排序。

单表达式闭包隐式返回

单行表达式闭包可以通过省略 return 关键字来隐式返回单行表达式的结果,

参数名称缩写

swift自动为内联闭包提供了参数名称缩写功能,可以直接通过$0,$1,$2来顺序条用闭包的参数,一次类推。
如果在闭包表达式中使用参数名称缩写,可以在闭包定义中省略参数列表,并且对应参数名称缩写的类型会通过函数类型进行推断。in 关键字也同样可以被省略,因为此时,闭包表达式完全由闭包函数体构成。

reversedNames = names.sorted(by:{$0>s1})
在这个例子中,$0和$1表示闭包中第一个和第二个String类型的参数。

运算符方法

swift的String类型定义了关于大于号的字符串实现,其作为一个函数接收两个String类型的参数并返回Bool类型的值。而这正好与sorted(by:)方法的参数需要的函数类型相符合。因此,你可以简单的传递一个大于号,swift可以自动的推断出你想使用大于号的字符串函数实现:

reversedNames = names.sorted(by:>)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容

  • 86.复合 Cases 共享相同代码块的多个switch 分支 分支可以合并, 写在分支后用逗号分开。如果任何模式...
    无沣阅读 1,340评论 1 5
  • 本章将会介绍 闭包表达式尾随闭包值捕获闭包是引用类型逃逸闭包自动闭包枚举语法使用Switch语句匹配枚举值关联值原...
    寒桥阅读 1,550评论 0 3
  • 闭包是自包含的函数代码块,可以在代码中被传递和使用。Swift 中的闭包与 C 和 Objective-C 中的代...
    莽原奔马668阅读 1,875评论 2 12
  • ——配图来自闲游视界的那木措湖 肌雪涌白柔化云朵 眼波荡蓝情映苍天 群峰酣舞信念电掣 金光现佛天湖恋歌 哦那木措海...
    流云满树阅读 193评论 0 1