Swift 閉包表達式⑥

?在Swift中定義一個函數(shù)有兩種方式
??1. 可以通過func定義一個函數(shù)
??2. 通過閉包表達式
閉包格式:

{
(參數(shù)列表)-> 返回值 in
? 函數(shù)體代碼
}

示例:

//函數(shù)
func sum(_ v1 : Int , _ v2 : Int) -> Int {
    return v1 + v2
}
print(sum(1, 2)) //3

//閉包1
var fn = {
    (v1 : Int , v2 : Int) -> Int in
    return v1 + v2
}
print(fn(1,2)) //3
//閉包2
print({
    (v1 : Int , v2 : Int) -> Int in
    return v1 + v2
    }(20,30)) //50

1. 閉包表達式的簡寫

//函數(shù)定義
func exec(v1: Int, v2: Int , fn: (Int, Int) -> Int){
    print(fn(v1,v2))
}
//調用
exec(v1: 10, v2: 20, fn: {
    (v1, v2) -> Int in
    return v1 + v2
})

//2
exec(v1: 10, v2: 20, fn: {
    (v1, v2) in return v1 + v2
    }
)
//3
exec(v1: 10, v2: 20, fn: {
        (v1, v2) in  v1 + v2 //如果函數(shù)體代碼就是一個單一的表單時,則return可以省略
    }
)
//4
exec(v1: 10, v2: 20, fn: {$0 + $1})//$0 第一個參數(shù)

//5
exec(v1: 10, v2: 20, fn: + )

2. 尾隨閉包

  • 如果將一個很長的閉包表達式作為函數(shù)的最后一個實參,使用尾隨閉包可以增強函數(shù)的可讀性
  • 尾隨閉包是一個書寫在函數(shù)調用括號外面(后面)的閉包表達式
exec(v1: 10, v2: 20){
    (v1, v2) -> Int in
    return v1 + v2
}

exec(v1: 10, v2: 20){$0 + $1}
  • 如果閉包表達式是函數(shù)唯一實參,而且使用了尾隨閉包的語法呢诬,那就不需要在函數(shù)后面寫圓括號
func execc(fn : (Int, Int) -> Int){
    print(fn(1,2))
}

execc(fn: {
    (v1, v2) -> Int in
    return v1 + v2
    }
)

execc { (v1, v2) -> Int in
    return v1 + v2
}

execc{$0 + $1}

3. 自動閉包

為了避免與期望沖突,使用了@autoclosure 的地方最好明確注釋清楚:這個值會被推遲執(zhí)行


func getFirstPositive(_ v1: Int, _ v2: Int) -> Int {
    return v1 > 0 ? v1 : v2
}

getFirstPositive(10, 20)//10
getFirstPositive(-2, 20)//20
getFirstPositive(0, -4)//-4



func sum( ) -> Int {
    let a = 10
    let b = 10
    return a + b
}
getFirstPositive(10, sum())//對于這種情況咆耿,即便v1>0,后面的sum還是會執(zhí)行戒良,浪費資源

//優(yōu)化
func getFirstPositive2(_ v1: Int, _ v2: ()->Int) -> Int {
    return v1 > 0 ? v1 : v2()
}

getFirstPositive2(10, {20})//10
getFirstPositive2(-2, {20})//20
getFirstPositive2(0, {-4})//-4
//autoclosure自動閉包  延遲加載
func getFirstPositive2(_ v1: Int, _ v2: @autoclosure()->Int) -> Int {
    return v1 > 0 ? v1 : v2()
}

getFirstPositive2(10, 20)//10
getFirstPositive2(-2, 20)//20
getFirstPositive2(0, -4)//-4
getFirstPositive2(2, sum())

  • @autoclosure 會自動將20 封裝成閉包 {20}
  • @autoclosure 只支持 ()-> T 格式的參數(shù)
  • @autoclosure 并非只支持最后一個參數(shù)
  • 空合并運算符?? 使用了- @autoclosure技術
  • @autoclosure 和 無@autoclosure構成了函數(shù)重載

4. 非逃逸閉包谋逻、逃逸閉包

非逃逸閉包殷绍、逃逸閉包染苛,一般都是當做參數(shù)傳遞給函數(shù)

非逃逸閉包 :閉包調用發(fā)生在函數(shù)結束之前,閉包調用在函數(shù)作用域內(nèi)
逃逸閉包 :閉包有可能在函數(shù)結束后調用主到,閉包調用逃離了函數(shù)的作用域殖侵,需要通過@escaping 聲明

typealias Fn = () -> ()
//fn 是非逃逸閉包
func test1(_ fn : Fn)  {
    fn()
}

var gFn : Fn?
//fn 是逃逸閉包
func test2(_ fn: @escaping Fn)  {
    gFn = fn
}

//fn 是逃逸閉包
func test3(_ fn: @escaping Fn) {
    DispatchQueue.global().async {
        fn()// 異步,可能不再函數(shù)作用域
    }
}

閉包

  1. 一個函數(shù)和它所捕獲的變量/常量環(huán)境組合起來镰烧。稱為閉包,
  • 一般指定義在函數(shù)內(nèi)部的函數(shù)楞陷。
  • 一般它捕獲的是外層函數(shù)的局部變量/常量
typealias Fn = (Int) -> Int
func getFn() -> Fn{
  //局部變量 num
    var num = 0
    func plus(_ i:Int) -> Int{
      //被捕獲后怔鳖,會在堆空間分配一個內(nèi)存用來存儲num
        num += i
        return num
    }
    return plus// 返回的plus 跟 捕獲的 num 組合起來叫做閉包,getFn只是一個函數(shù)
}
// 上面閉包的簡寫方式
func getFnS() -> Fn{
    var num = 0
    
    return {
        num += $0
        return num
    }
}

var fn1 = getFn()
var fn2 = getFn()
print(fn1(1))//1
print(fn2(2))//2
print(fn1(3))//4
print(fn2(4))//6
  1. 可以把閉包想象成一個類的實例對象
  • 內(nèi)存在堆空間
  • 捕獲的局部變量/常量就是對象的成員(存儲屬性)
  • 組成閉包的函數(shù)就是類內(nèi)部定義的方法
class Closure {
    var num = 0
    func plus(_ i: Int) -> Int {
        num += i
        return num
    }
    
}

var c1 = Closure()
var c2 = Closure()

c1.plus(1)//1
c2.plus(2)//2
c1.plus(3)//4
c2.plus(4)//6
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末固蛾,一起剝皮案震驚了整個濱河市结执,隨后出現(xiàn)的幾起案子度陆,更是在濱河造成了極大的恐慌,老刑警劉巖献幔,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件懂傀,死亡現(xiàn)場離奇詭異,居然都是意外死亡蜡感,警方通過查閱死者的電腦和手機蹬蚁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來郑兴,“玉大人犀斋,你說我怎么就攤上這事∏榱” “怎么了叽粹?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長却舀。 經(jīng)常有香客問我虫几,道長,這世上最難降的妖魔是什么挽拔? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任辆脸,我火速辦了婚禮,結果婚禮上篱昔,老公的妹妹穿的比我還像新娘每强。我一直安慰自己,他們只是感情好州刽,可當我...
    茶點故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布空执。 她就那樣靜靜地躺著,像睡著了一般穗椅。 火紅的嫁衣襯著肌膚如雪辨绊。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天匹表,我揣著相機與錄音门坷,去河邊找鬼。 笑死袍镀,一個胖子當著我的面吹牛默蚌,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播苇羡,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼绸吸,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起锦茁,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤攘轩,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后码俩,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體度帮,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年稿存,在試婚紗的時候發(fā)現(xiàn)自己被綠了笨篷。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡挠铲,死狀恐怖冕屯,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情拂苹,我是刑警寧澤安聘,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站瓢棒,受9級特大地震影響浴韭,放射性物質發(fā)生泄漏。R本人自食惡果不足惜脯宿,卻給世界環(huán)境...
    茶點故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一念颈、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧连霉,春花似錦榴芳、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至歉井,卻和暖如春柿祈,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背哩至。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工躏嚎, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人菩貌。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓卢佣,卻偏偏與公主長得像,于是被迫代替她去往敵國和親箭阶。 傳聞我的和親對象是個殘疾皇子珠漂,可洞房花燭夜當晚...
    茶點故事閱讀 45,691評論 2 361