Swift --閉包表達式與閉包(彙編分析)

在Swift中,能夠經過func定義一個函數,也能夠經過閉包表達式定義一個函數!數組

1、閉包表達式

概念

閉包表達式與定義函數的語法相對比,有區別以下:閉包

  1. 去除了func
  2. 去除函數名
  3. 返回值類型添加了關鍵字in
  4. { }放在形參列表的前邊

閉包表達式的形式以下:函數

{ 

   (參數列表) -> 返回值類型 in

     函數體代碼

 }

 

講解

舉例1  閉包表達式做爲變量或者常量的值優化

 調用閉包表達式不須要寫參數v1,v2,直接調用fn0(10,20)就能夠spa

舉例2 閉包表達式做爲函數的返回值3d

舉例3 閉包表達式做爲函數的實參code

下面講述sorted(by:)方法定義和語法優化方式,來展現閉包表達式不一樣的表達方式達到一樣的效果!blog

講述以前先簡單介紹下sorted方法, Swift標準庫提供了sorted(by:)方法,會將已知類型數組中的值進行排序. 一旦進行了排序會返回和原數組大小相同,包含同類型元素而且是正確排序的數組,如例3. 排序

sorted(by:)方法接受一個閉包,該閉包函數須要傳入元素類型的兩個值,並返回Bool值,完成排序,排序閉包函數類型需爲(String, String) -> Bool內存

在上面的兩種寫法中,都寫成了(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的倍數--常識)

相關文章
相關標籤/搜索