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


本人已遷移博客至掘進,以后會在掘進平台更新最新的文章也會有更多的干貨,歡迎大家關注!!!https://juejin.im/user/588993965333309

 

在Swift中,可以通過func定義一個函數,也可以通過閉包表達式定義一個函數!

一、閉包表達式

概念

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

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

閉包表達式的形式如下:

{ 

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

     函數體代碼

 }

 

講解

舉例1  閉包表達式作為變量或者常量的值

 調用閉包表達式不需要寫參數v1,v2,直接調用fn0(10,20)就可以

舉例2 閉包表達式作為函數的返回值

舉例3 閉包表達式作為函數的實參

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

講述之前先簡單介紹下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: <)

 

尾隨閉包

如果將很長的閉包表達式作為函數的最后一個實參,使用尾隨閉包可以增強函數的可讀性

尾隨閉包是一個被書寫在函數調用括號外面(后面)的閉包表達式

 如果閉包表達式是函數的唯一實參,而且使用了尾隨閉包的語法, 那就不需要在函數名后寫圓括號

 

二、閉包

閉包: 一個函數和它所捕獲的變量/常量環境組合起來

  • 一般指定義在函數內部的函數
  • 一般它捕獲的是外層函數的局部變量/常量

看如下閉包,返回的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的倍數--常識)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM