在一些語言中,有 try/finally
這樣的控制語句,好比 Java。這種語句能夠讓咱們在 finally
代碼塊中執行必需要執行的代碼,無論以前怎樣的興風做浪。在 Swift 2.0 中,Apple 提供了 defer
關鍵字,讓咱們能夠實現一樣的效果。swift
func checkSomething() { print("CheckPoint 1") doSomething() print("CheckPoint 4") } func doSomething() { print("CheckPoint 2") defer { print("Clean up here") } print("CheckPoint 3") } // CheckPoint 1, CheckPoint 2, CheckPoint 3, Clean up here, CheckPoint 4 checkSomething()
CheckPoint 2
以後並無打印出 Clean up here
,而是 CheckPoint 3
,這就是 defer
的做用,它對進行了 print("Clean up here")
延遲。在你的代碼塊就要結束前。若是你使用了 defer
。在其之中的代碼就會運行。等於說,給了你最後的機會來進行一些處理。若是你熟悉 BDD 或者 TDD,那麼你能夠參考他們中的 aferAll
機制。app
func myFunction() throws { defer { // No matter what happened I need do something print("All done, clean up here") } guard let item = item else { // need throws the error out throw MyError.notExist } guard item.count > maxNumber else { // need throws the error out throw MyError.outOfRange } // do something with item // ... }
若是你有多個 defer
語句,他們在執行的順序會和棧同樣,最後一個進,第一個出。fetch
咱們再來看一個 I/O 的示例code
func writeSomething() { let file = OpenFile() let ioStatus = fetchIOStatus() guard ioStatus != "error" else { return } file.write() closeFile(file) }
ioStatus
正常,那麼該方法沒有問題,若是 ioStatus
取到的是 error
,那麼會被 guard
語句抓到執行 return
操做,這樣的話 closeFile(file)
就永遠都不會執行了,一個嚴重的 Bug 就這樣產生了。下面咱們看看如何用 defer
來解決這個問題。it
func writeSomething() { let file = OpenFile() defer { closeFile(file) } let ioStatus = fetchIOStatus() guard ioStatus != "error" else { return } file.write() }
closeFile(file)
放在 defer
代碼塊裏,這樣即便 ioStatus
爲 error
,在執行 return
前會先執行 defer
裏的代碼,這樣就保證了無論發生什麼,最後都會將文件關閉。