Swift Defer 延遲調用

一、Defer

  • 在一些語言中,有 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

二、Defer 示例

  • 咱們再來看一個 I/O 的示例code

    func writeSomething() {
    
        let file = OpenFile()
    
        let ioStatus = fetchIOStatus()
    
        guard ioStatus != "error" else {
            return
        }
    
        file.write()
    
        closeFile(file)
    }
    • 上述示例是一個 I/O 操做的僞代碼,若是獲取到的 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 代碼塊裏,這樣即便 ioStatuserror,在執行 return 前會先執行 defer 裏的代碼,這樣就保證了無論發生什麼,最後都會將文件關閉。
相關文章
相關標籤/搜索