闭包表达式(Closure Expression)

可以通过func定义一个函数,也可以通过闭包表达式定义一个函数

  • func函数

  • 闭包定义函数

闭包表达式调用可以直接省略参数名

闭包定义函数也可以写为:

  • 闭包表达式的结构


闭包表达式的简写


尾随闭包

如果将一个很长的闭包表达式作为函数的最后一个实参,使用尾随闭包可以增强函数的可读性

尾随闭包是一个被书写在函数调用括号外面(后面)的闭包表达式

上面的函数使用闭包调用:

如果闭包表达式是函数的唯一实参,而且使用了尾随闭包的语法,那就不需要在函数名后边写圆括号

针对上面的函数,一般与闭包调用的对比:


示例 - 数组的排序

数组排序的底层代码的定义:

由上面的底层代码可知,想要自定义一个数组排序,只需要传入一个有两个参数,返回值是Bool的函数

自定义排序方法的多种调用方式(闭包和简写):


闭包(Closure)

网上有各种关于闭包的定义,个人觉得比较严谨的定义是 :

  • 一个函数和它所捕获的变量\常量环境组合起来,称为闭包
  • 一般指定义在函数内部的函数
  • 一般它捕获的是外层函数的局部变量\常量

定义了一个闭包:

注:return plus前分配了一段堆空间,将num的值存储到了这个堆空间,调用plus访问的num实际上是堆空间的num, plus方法实际接收了两个参数:i和堆空间地址

使用反汇编看它实现的底层汇编代码:

由图上红色框标注的汇编代码我们可以看出,在闭包里调用了swift_allocObject方法,我们可以理解为它在堆区申请了一块内存空间,用来存储它捕获的外层函数的局部变量或常量也就是num,这也就决定了num不会立刻销毁,由此我们可以看下它的计算结果:

func getFn() -> Fn {var num = 0func plus(_ i: Int) -> Int{num += 1return num}return plus
}var fn = getFn()
print(fn(1))  //结果为1
print(fn(2))  //结果为3
print(fn(3))  //结果为6
print(fn(4))  //结果为10

可以看出计算结果是累加的,那就因为num存储在堆空间,没有销毁,上面的计算是对num的不断累加。

注意:如果num是全局变量,则不会在堆空间开辟内存。

注意:每调用一次getFn()都会申请一个新的内存空间,举例如下:

由上面的计算可以看出,fn1和fn2是分开独立累加的,也就是fn1和fn2分别开辟了一块新内存,互不影响

反汇编代码如下:

由上面的反汇编代码可以看出fn1和fn2前8个字节相同,因为都是指向同一个plus方法,但是后8个字节不同,因为分配的堆空间不同。

  • 可以把闭包想象成是一个类的实例对象
  • 内存在堆空间
  • 捕获的局部变量\常量就是对象的成员(存储属性)
  • 组成闭包的函数就是类内部定义的方法


闭包举例

  • 第一个例子:

上面的闭包可以看成一个类:

  • 第二个例子:

上面的闭包同样可以看成一个类:


参数注意

如果返回值类型是函数类型,那么参数的修饰要保持统一


自动闭包

  • @autoclosure 会自动将 20 封装成闭包 { 20 }
  • @autoclosure 只支持 () -> T 格式的参数
  • @autoclosure 并非只支持最后1个参数
  • 空合并运算符 ?? 使用了 @autoclosure 技术
  • 有@autoclosure、无@autoclosure,构成了函数重载

为了避免与期望冲突,使用了@autoclosure的地方最好明确注释清楚:这个值会被推迟执行。

Swift学习(八):闭包(闭包表达式,尾随闭包,闭包的定义,自动闭包)相关推荐

  1. Swift学习笔记 闭包表达式

    闭包是功能性自包含模块,可以在代码中被传递和使用. Swift 中的闭包与 C 和 Objective-C 中的 blocks 以及其他一些编程语言中的 lambdas 比较相似. 闭包的形式主要有三 ...

  2. Swift 学习总结三:数组,字典,枚举,闭包, 函数

    数组 ///创建数组//创建某一类型的含有n个初始元素的数组var array1 = [Int](repeating: 5, count: 3)//创建某一类型空数组var array2 = [Int ...

  3. Swift学习之闭包

    文章目录 闭包的定义 闭包简化 闭包使用 尾随闭包 闭包捕获上下文中的变量和常量 给闭包启别名 闭包的定义 一门语言要支持闭包有两个前提: 支持函数类型,能够将函数作为参数或返回值传递 支持函数嵌套. ...

  4. Swift-闭包,隐式返回、尾随闭包、值捕获、逃逸闭包、自动闭包

    闭包 闭包可以捕获和存储其所在上下文中任意常量和变量的引用,被称为包裹常量和变量. Swift 会为你管理在捕获过程中涉及到的所有内存操作. 全局和嵌套函数实际上也是特殊的闭包,闭包采用如下三种形式之 ...

  5. Swift中使用typealias定义一个闭包closure

    在OC中我们定义一个Blocks是这样定义的: typedef void (^ZWProgressHUDCompletionBlock)(); 在Swift中定义一个闭包是这种: typealias ...

  6. go 变量在其中一个函数中赋值 另一个函数_go 学习笔记之仅仅需要一个示例就能讲清楚什么闭包...

    本篇文章是 Go 语言学习笔记之函数式编程系列文章的第二篇,上一篇介绍了函数基础,这一篇文章重点介绍函数的重要应用之一: 闭包 空谈误国,实干兴邦,以具体代码示例为基础讲解什么是闭包以及为什么需要闭包 ...

  7. JavaScript学习(五十九)—原型、原型链、闭包以及闭包的不足

    JavaScript学习(五十九)-原型.原型链.闭包以及闭包的不足 一.什么是闭包? 所谓闭包就是指被定义在其他函数内部的函数. 闭包函数可以访问它所在的函数的所有变量. 文字太抽象了,画图解释一下 ...

  8. go 学习笔记之仅仅需要一个示例就能讲清楚什么闭包

    本篇文章是 Go 语言学习笔记之函数式编程系列文章的第二篇,上一篇介绍了函数基础,这一篇文章重点介绍函数的重要应用之一: 闭包 空谈误国,实干兴邦,以具体代码示例为基础讲解什么是闭包以及为什么需要闭包 ...

  9. Go 学习笔记(18)— 函数(04)[闭包定义、闭包修改变量、闭包记忆效应、闭包实现生成器、闭包复制原对象指针]

    1. 闭包定义 Go 语言中闭包是引用了自由变量的函数,被引用的自由变量和函数一同存在,即使已经离开了自由变量的环境也不会被释放或者删除,在闭包中可以继续使用这个自由变量,因此,简单的说: 函数 + ...

最新文章

  1. Nature解析中国AI现状,2030年能引领全球吗?
  2. JAVA SE学习day_11:集合的相关应用、增强型for循环、foreach方法、数组与集合的相互转换
  3. 利用邻接表完成图的BFS和DFS
  4. 如何使用python numpy中的数组复制
  5. Cuckoo WIndows 安装
  6. C语言 · FJ的字符串
  7. RHEL 5基础篇—常见系统启动类故障
  8. Android修改项目包名
  9. 【人工智能课程实验】 - 利用贝叶斯分类器实现手写数字 的识别
  10. 因限制游戏驿站等WSB概念股交易 Robinhood遭散户集体诉讼
  11. 关于mail-notification和apt-get
  12. jQuery复习:第五章
  13. 黑客入侵 - 认识黑客入侵的利器 嗅探软件
  14. 外卖返利小程序定制美团饿了么返利系统公众号外卖返利源码代搭建
  15. 学Python兼职赚钱是真的吗
  16. (附源码)记账微信小程序 毕业设计180815
  17. 计算机专业mx330够用吗,这款新的HP笔记本电脑配备了MX330图形卡,那么性能如何?...
  18. 解决以Error: GlobalConfigUtils setMetaData Fail ! 为基础的嵌套问题(包括common troller,commonservice等问题)
  19. 转载关于KeyPress和KeyDown事件的区别和联系
  20. 计算机查询网络连接,本地网络查询方法大全

热门文章

  1. 应用软件创业神话 80后月入过百万
  2. 软件工程--四则运算表达式(4)
  3. 暴击java7723_热血足球之暴力闯关版
  4. 百度二级域名批量绑定软件,绕过验证码错误机制
  5. C#使用PrintDocument实现打印预览
  6. Java 设计模式归纳(观察者、工厂、单例、策略、适配器、命令、装饰者、外观、模板方法、状态
  7. 基于matlab的模拟相位调制,基于MATLAB的相位调制系统仿真分析
  8. 知网导出引用文件,插入到Endnote管理文献
  9. 去掉ul li开头前的空白
  10. Windows mobile模拟器上网的配置步骤