swift 中的閉包類似于 OC 中的 Block,但是使用比 Block 更廣泛
閉包的簡單說明
- 保存提前準備好的代碼
- 在需要的時候執(zhí)行
- 可以當做參數傳遞
- 在 OC 中 Block 是匿名的函數
- 在 Swift 中閉包是特殊的函數
閉包的使用場景
- 異步執(zhí)行完成回調
- 控制器間回調
- 自定義視圖回調
- 回調的特點
- 以參數回調處理結果
- 返回值為 Void
閉包的簡單使用
-
無參數無返回值
//最簡單的閉包(無返回值無參數) // ( ) -> ( ) let bibao1 = { print("hello, world") } //調用閉包 bibao1()
-
有參數無返回值
- 在閉包中,參數桨仿、返回值慕爬、實現代碼都可以寫在 { } 中
- 使用一個關鍵字
in
分割定義和實現 - { 形參列表 -> 返回值類型 in //實現代碼 }
//帶參數無返回值的閉包 // ( Int ) -> ( ) let bibao2 = { (x: Int) -> () in print(x) } bibao2(10)
-
有參數有返回值
//帶參數帶返回值的閉包 // (Int) -> Int let bibao3 = { (x: Int) -> Int in return x + 10 } print(bibao3(10))
閉包作為參數傳遞
-
閉包和 Block 一樣可以作為參數進行傳遞
//閉包作為參數傳遞 // (Int, Int) -> Int let bibao4 = { (x: Int, y: Int) -> Int in return x + y } func test(x: Int, y: Int, bibao: (Int, Int) -> Int) { bibao(x, y) } test(x: 10, y: 20, bibao: bibao4)
尾隨閉包
如果函數的最后一個參數是閉包台囱,函數參數可以提前結束,最后的一個參數使用 { } 來包裝閉包的代碼
-
使用尾隨閉包對上述的參數傳遞代碼進行調整兵琳,可以使用以下方式進行修改
//尾隨閉包 func test(x: Int, y: Int, bibao: (Int, Int) -> Int) { bibao(x, y) } test(x: 10, y: 20) { (x, y) -> Int in return x + y }
逃逸閉包
在 Swift 中 閉包默認是非逃逸的,不能被其他對象引用
-
@escaping 修飾的就是逃逸閉包骇径,可以被其他對象引用
func test(a: Int, aa: ()->()) { aa() } func getData(result: @escaping ([String]) -> ()) { test(a: 10, aa: { result(["1", "2"]) }) }
閉包的循環(huán)引用
- 由于 { } 的作用域躯肌,在使用閉包的同時要注意循環(huán)引用的問題
- 在 OC 中可以使用 weak 和 unsafe_unretained 兩種方式
- 在 Swift 中主要使用 weak 和 unowned 兩種方式來解決
weak
- Swift 中推薦使用的方法
- 需要注意解包問題
- 修飾的 self 都是弱引用
```objc
class Person {
var num: Int = 0
var bb: (() -> ())?
// weak 方式一
func test1() {
weak var weakSelf = self
bb = {
print("test1", weakSelf!)
let pr = weakSelf?.num
pr! + 10
}
bb!()
}
// weak 方式二
func test2() {
bb = {
//標識,在這個閉包里使用的所有 self 都是弱引用
[weak self]
() -> () in
print(self!)
print(self!)
}
bb!()
}
}
```
-
unowned
- 修飾的 self 都是 assign 的破衔,不會強引用
- 如果對象釋放清女,指針地址不會變化
- 若被釋放之后繼續(xù)調用,會出現野指針問題
class Person { var num: Int = 0 var bb: (() -> ())? // unowned 方式一 func test1() { unowned let weakSelf = self bb = { print("test1", weakSelf) let pr = weakSelf.num pr + 10 } bb!() } // unowned 方式二 func test2() { bb = { //標識晰筛,在這個閉包里使用的所有 self 都是弱引用 [unowned self] () -> () in print(self) print(self) } bb!() } }