iT邦幫忙

2022 iThome 鐵人賽

DAY 19
0

今天來繼續我們的閉包。

值捕獲

閉包可以在其被定義的上下文中捕獲常量或變量。Swift 中,嵌套函數最簡單捕獲,也就是定義在其他函數裡面的函數。嵌套函數也能捕獲外部函數的參數以及定義的常量和變量。
來看一下官方的例子。

func makeIncrementer(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementer() -> Int {
        runningTotal += amount
        return runningTotal
    }
    return incrementer
}

makeIncreamenter(forIncrement:) 裡面定義了一個初始值為 0 的變量 runninTotal ,用來儲存總計數值,該值為 incrementer 的返回值。
而 他自己有一個參數值 amount 該參數會被裡面的 incrementer 函數拿來調用並且依照 amount 數值 增加 runningTotal 並將其返回。

閉包是引用類型

let incrementByTen = makeIncrementer(forIncrement: 10)
incrementByTen()
// 返回10
incrementByTen()
// 返回20
incrementByTen()
// 返回30
let alsoIncrementByTen = incrementByTen
alsoIncrementByTen()
// 返回50

上面的例子 incrementByTen 都是常量,但是這些常量指向的閉包還是可以增加裡面的變量值。這是因為函數跟閉包都是引用類型。

逃逸閉包

顧名思義它能逃出來,但要在前面標註 @escaping 來指名說他是逃逸閉包。
比較常用來做網路請求,因為逃逸閉包會有一個延遲的效果。

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

func someFunctionWithNonescapingClosure(closure: () -> Void) {
    closure()
}

class SomeClass {
    var x = 10
    func doSomething() {
        someFunctionWithEscapingClosure { self.x = 100 }
        someFunctionWithNonescapingClosure { x = 200 }
    }
}

let instance = SomeClass()
instance.doSomething()
print(instance.x)
// 打印出“200”

completionHandlers.first?()
print(instance.x)
// 打印出“100”

逃逸閉包在裡面要顯示的引用 self 而 非逃逸閉包就可以隱式引用 self 差別在逃逸閉包比較容易可能有循環引用,而非逃逸閉包就沒有這個問題。所以通常都會避免太常使用,所以比較常看到在網路請求的部分使用。

OK 今天就到這裡。


上一篇
30天的 iOS 修仙道路 (18)
下一篇
30天的 iOS 修仙道路 (20)
系列文
30天的 iOS 修仙道路 站穩腳步基礎篇30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言