標籤:函數 swift
1、什麼是閉包
閉包簡單的來說就是匿名函數、lambdas函數,書面點的來說就是閉包是自包含的函數代碼塊,可以在代碼中被傳遞和使用,可以捕獲和儲存其所在上下文中任意常量和變數的引用。 這就是所謂的閉合并包裹著這些常量和變數,俗稱閉包。
2、閉包採取的形式
前面在函數文章中,都定義的是全域函數,以及內嵌函數 實際上都是閉包的一種特殊形式。
- 全域函數是一個有名字但不會捕獲任何值的閉包
- 嵌套函數是一個有名字並可以捕獲其封閉函數域內值的閉包
- 閉包運算式是一個利用輕量級文法所寫的可以捕獲其上下文中變數或常量值的匿名閉包
4、全域函數和嵌套函數已經熟悉了,那來看下閉包運算式。
閉包運算式是一種利用簡潔文法構建內聯閉包的方式。它提供了一些文法最佳化,使得撰寫閉包變得簡單明了。下面來分析下它怎麼簡單明了。
5、樣本:sorted函數(Swift 標準庫提供了sorted函數,會根據您提供的基於輸出類型排序的閉包函數將已知類型數組中的值進行排序。 一旦排序完成,函數會返回一個與原數組大小相同的新數組,該數組中包含已經正確排序的同類型元素。)
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
func backwards(s1: String, s2: String) -> Bool { return s1 > s2}var reversed = sorted(names, backwards)// reversed 為 ["Ewa", "Daniella", "Chris", "Barry", "Alex"]
sorted函數需要傳入兩個參數:
- 已知類型的數組
- 閉包函數,該閉包函數需要傳入與數群組類型相同的兩個值,並返回一個布爾類型值來告訴
sorted函數當排序結束後傳入的第一個參數排在第二個參數前面還是後面。如果第一個參數值出現在第二個參數值前面,排序閉包函數需要返回true,反之返回false。
閉包的一般運算式
{ (parameters) -> returnType in statements}
那上面的調用方法可以最佳化成什麼樣子呢。
reversed = sorted(names, { (s1: String, s2: String) -> Bool in return s1 > s2})
in 關鍵字,他表示參數和返回值定義完成,函數體即將開始。
swift是一個參數類型確定的語言,它也能夠推斷參數類型。所以這裡還可以這樣寫。
reversed = sorted(names, { s1, s2 in return s1 > s2 } )
對於單運算式閉包,還可以隱藏return關鍵字。
reversed = sorted(names, { s1, s2 in s1 > s2 } )
Swift 自動為內嵌函式提供了參數名稱縮寫功能,您可以直接通過
$0,
$1,
$2來順序調用閉包的參數。
reversed = sorted(names, { $0 > $1 } )
還可以是用運算子函數
reversed = sorted(names, >)
不過說了這麼多。可讀性就被完全抹殺了。。。
那如果需要在閉包中輸入很長的函數體,那就麻煩了。讀起來不方便,所以就有了尾隨閉包。閉包放在函數尾巴上。
那上面可以寫成:
reversed = sorted(names) { $0 > $1 }
6、值捕獲
閉包可以在其定義的上下文中捕獲常量或變數。 即使定義這些常量和變數的原域已經不存在,閉包仍然可以在閉包函數體內引用和修改這些值。
func makeIncrementor(forIncrement amount: Int) -> () -> Int { var runningTotal = 0 func incrementor() -> Int { runningTotal += amount return runningTotal } return incrementor}
通過前面的接觸,上面這個函數看懂了麼。。。
這個函數接收一個叫forIncrement的外部參數名的Int參數,並返回一個()->Int 的函數類型。
在內嵌函數中沒有接收runningTotal這個參數也能使用,就是內嵌函數捕獲了包含它的函數體內的變數
閉包是參考型別
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
【Swift】學習筆記(七)——閉包