Swift中的逃逸閉包的理解

來源:互聯網
上載者:User
逃逸閉包的書面定義

一個傳入函數的閉包如果在函數執行結束之後才會被調用,那麼這個閉包就叫做逃逸閉包。 對定義的理解

通過定義我們知道,逃逸閉包首先是一個閉包(感覺有點廢話),但是逃逸閉包又不是普通的閉包,因為它會在函數結束後才執行(這是特點)。 什麼閉包會在函數執行之後才執行呢?

很多啟動非同步作業的函數接受一個閉包參數作為 completion handler。這類啟動非同步作業的函數會在非同步作業開始之後(即“啟動非同步作業”的函數已經執行完畢)立刻返回,但是閉包直到非同步作業結束後才會被調用(即“啟動非同步作業”函數執行完畢後才被調用)。這中情況很完美的符合了逃逸閉包的定義……
看一個例子:

var completionHandlers: [() -> Void] = []func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {    completionHandlers.append(completionHandler)}

上面這段代碼定義了一個全域變數completionHandlers這個全域變數是一個數組,內部專門用來存放沒有參數、沒有傳回值的閉包,同時定義了函數someFunctionWithEscapingClosure,這個函數接收了一個閉包,並將這個閉包添加到外部全域數組中。然後函數結束(注意:此時傳入的閉包並沒有執行,僅僅是添加到全域數組中)。

接下來完善一下上面的代碼:

//定義一個存放閉包的全域數組var completionHandlers: [() -> Void] = []//定義一個接收閉包的函數func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {    completionHandlers.append(completionHandler)}//定義另一個接收閉包的函數func someFunctionWithNonescapingClosure(closure: () -> Void) {    closure()}/*定義一個類:初始化x值為10通過調用上面定義的兩個函數,使用尾隨閉包的方式將實現"對x賦值"這麼一個功能的閉包傳入*/class SomeClass {    var x = 10    func doSomething() {        someFunctionWithEscapingClosure { self.x = 100 }        someFunctionWithNonescapingClosure { x = 200 }    }}//建立類的對象let instance = SomeClass()/*執行doSomething函數PS:內部執行someFunctionWithEscapingClosure,someFunctionWithNonescapingClosure,即期望內部會利用兩個尾隨閉包對x進行賦值*/instance.doSomething()print(instance.x)// 列印出 "200"completionHandlers.first?()print(instance.x)// 列印出 "100"

看了這段代碼的輸出結果,我一開始是很詫異的,因為對於逃逸閉包的不理解,所以很難理解為什麼第二次列印會輸出的是100。 對於代碼執行結果的解釋

因為逃逸閉包是在函數執行之後才會執行,所以可以這麼理解: 我建立了一個類的對象instance 對象中初始化了一個x = 10 利用對象執行了函數doSomething 函數內部先調用了全域函數someFunctionWithEscapingClosure該函數傳入了尾隨閉包{ self.x = 100 },期望修改instance對象中的x值為100(但是此時並沒有執行這個包含了指派陳述式的閉包) 函數內部進一步調用全域函數someFunctionWithNonescapingClosure該函數傳入了尾隨閉包{ x = 200 },期望修改instance對象中的x值為200(因為此時全域函數someFunctionWithNonescapingClosure內部執行這個包含了指派陳述式的閉包,所以x的值由10變為了200) 輸出(顯然結果為200) 尋找全域數組completionHandlers,找到裡面第一個元素,顯然找到的是在someFunctionWithEscapingClosure函數中添加的閉包{ self.x = 100 },此時才通過全域數組的查詢找出閉包並執行,於是x此時才被賦值為100(典型的someFunctionWithEscapingClosure函數執行完畢後才執行閉包{ self.x = 100 },於是這個在函數之後最後才執行到的閉包,就是符合定義的逃逸閉包了。 結論

逃逸閉包將在函數執行之後執行,於是這段代碼最後輸出為100是因為閉包最後才被執行……

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.