Swift - closures and closure expression (compilation, analysis)

In the Swift, by func you define a function, can also closure expression defines a function!

First, the closure expression

concept

Closure function expression syntax defined contrast, there are the following differences:

  1. In addition to func
  2. Remove the function name
  3. Return Value added keywords in
  4. {} On the front of the list parameter

Closure form expression as follows:

{ 

   (Parameter list) -> return type in 

     function body 

 }

 

explain

Example 1   closure expression as the value of the variable or constant

 Call closure expressions do not need to write parameters v1, v2, direct call fn0 (10,20) can be

Example 2 Expression closure as the return value of the function

Example 3 Expression closure as a function of argument

The following describes sorted (by :) syntax definitions and methods to optimize the way, to show a different expression closures expression to achieve the same effect!

Before introducing the method briefly introduce sorted, Swift standard library provides a sorted (by :) method, the value of the type known in the array will be sorted. Once the same sort, and returns the size of the original array, and the elements comprising the same type sorted array is correct, as in Example 3. 

sorted (by :) method takes a closure, the closure function values ​​need to pass two types of elements, and return values ​​Bool completed, the sort required for the closure function type (String, String) -> Bool

In the above two way it is written (String, String) -> Bool, the closure expression and function return values ​​are written in a type of braces, rather than outside the braces.

The following simplified constantly follows

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: <)

 

尾随闭包

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

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

 

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

 

 

二、闭包

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

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

看如下闭包,返回的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的倍数--常识)

 

Guess you like

Origin www.cnblogs.com/guohai-stronger/p/12421590.html