Swift @escaping @ noescaping 逃逸閉包與非逃逸閉包
阿新 • • 發佈:2019-01-06
閉包只有在函式中做引數時才會區分逃逸閉包和非逃逸閉包。
Swift 3.0之後,傳遞閉包到函式中的時候,系統會預設為非逃逸閉包型別(NonescapingClosures)@noescaping,逃逸閉包在閉包前要新增@escaping關鍵字。
從生命週期看兩者區別:
非逃逸閉包的生命週期與函式相同:
1,把閉包作為引數傳給函式;
2,函式中呼叫閉包;
3,退出函式。結束
逃逸閉包的生命週期:
1,閉包作為引數傳遞給函式;
2,退出函式;
3,閉包被呼叫,閉包生命週期結束
即逃逸閉包的生命週期長於函式,函式退出的時候,逃逸閉包的引用仍被其他物件持有,不會在函式結束時釋放
例如:
非逃逸閉包:
程式碼執行順序(1),(2),(3)
當傳遞閉包引數給函式loadData時,要注意ViewController中的屬性tools,雖然閉包會捕獲self,但是由於預設閉包引數是非逃逸型,這裡可以省略self,編譯器已經知道這裡不會有迴圈引用的潛在風險。
逃逸閉包:
程式碼執行順序:(1),(3),(2)
當傳遞閉包引數給函式loadData時,要注意ViewController中的屬性tools,這裡閉包函式的生命週期在函式結束後結束,tools前面省略的self 就有必要做特殊處理,防止造成死迴圈。逃逸閉包前面新增@escaping關鍵字,這裡閉包的生命週期不可預知。
經常使用逃逸閉包的2個場景:
- 非同步呼叫: 如果需要排程佇列中非同步呼叫閉包,比如網路請求成功的回撥和失敗的回撥,
- 儲存: 需要儲存閉包作為屬性,全域性變數或其他型別做稍後使用,例子待補充。