Swift --闭包表达式与闭包(汇编分析)

在Swift中,能够经过func定义一个函数,也能够经过闭包表达式定义一个函数!html

1、闭包表达式

概念

闭包表达式与定义函数的语法相对比,有区别以下:数组

  1. 去除了func
  2. 去除函数名
  3. 返回值类型添加了关键字in
  4. { }放在形参列表的前边

闭包表达式的形式以下:闭包

{    (参数列表) -> 返回值类型 in  函数体代码 }

 

讲解

举例1  闭包表达式做为变量或者常量的值函数

 调用闭包表达式不须要写参数v1,v2,直接调用fn0(10,20)就能够优化

举例2 闭包表达式做为函数的返回值spa

举例3 闭包表达式做为函数的实参3d

下面讲述sorted(by:)方法定义和语法优化方式,来展现闭包表达式不一样的表达方式达到一样的效果!code

讲述以前先简单介绍下sorted方法, Swift标准库提供了sorted(by:)方法,会将已知类型数组中的值进行排序. 一旦进行了排序会返回和原数组大小相同,包含同类型元素而且是正确排序的数组,如例3. htm

sorted(by:)方法接受一个闭包,该闭包函数须要传入元素类型的两个值,并返回Bool值,完成排序,排序闭包函数类型需为(String, String) -> Boolblog

在上面的两种写法中,都写成了(String, String) -> Bool, 在闭包表达式中函数和返回值类型都写在了大括号内,而不是大括号以外.

下面不断简化的以下

let arr = ["hello","world","guohai"] ///闭包表达式当作参数
//写法一
let sortArr0 = arr.sorted{(str1: String, str2: String) -> Bool in
    return str1 < str2 } //写法二: 省去了参数类型
let sortArr1 = arr.sorted{(str1, str2) -> Bool in
    return str1 < str2 } //写法三: 若是返回值是单一表达式,可省去return
let sortArr2 = arr.sorted{(str1, str2) -> Bool in str1 < str2 } //写法四: 若是编译器能够肯定返回值,能够去除返回值类型
let sortArr3 = arr.sorted{(str1, str2) in str1 < str2 } //写法四: Swift闭包表达式能够不明显写出参数名,能够用美圆符$表示
let sortArr4 = arr.sorted{$0 < $1} //写法五: 编译器,对于$0 < $1和直接<效果同样
let sortArr5 = arr.sorted(by: <)

 

尾随闭包

若是将很长的闭包表达式做为函数的最后一个实参,使用尾随闭包能够加强函数的可读性

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

 若是闭包表达式是函数的惟一实参,并且使用了尾随闭包的语法, 那就不须要在函数名后写圆括号

 

2、闭包

闭包: 一个函数和它所捕获的变量/常量环境组合起来

  • 通常指定义在函数内部的函数
  • 通常它捕获的是外层函数的局部变量/常量

看以下闭包,返回的plus和num造成了闭包

typealias Fn = (Int) -> Int func getFn() -> Fn { var num = 0 func plus(_ i: Int) ->Int { num += i return num } return plus } var fn = getFn() print(fn(1)) print(fn(2)) print(fn(3)) print(fn(4))

若是你们看不出上面的结果,能够将var num = 0放在外面是全局变量,以下

 全局变量num时,结果是不断的叠加,若是仍是回到上一个,将num = 0移植到函数内部变成局部变量,和plus造成闭包,结果又如何呢? 

 发现结果是同样的,下面来探究本质!

查看上面代码汇编代码以下

 

 上面四次fn操做,调用访问的同一内存num,由于闭包的做用将局部变量num放进了堆空间,因此num不会被销毁!

拓展:(iOS底层堆空间分配的大小是16的倍数--常识)

 

原文出处:https://www.cnblogs.com/guohai-stronger/p/12421590.html