Swift Defer 延迟调用

Posted qianchia

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Swift Defer 延迟调用相关的知识,希望对你有一定的参考价值。

1、Defer

  • 在一些语言中,有 try/finally 这样的控制语句,比如 Java。这种语句可以让我们在 finally 代码块中执行必须要执行的代码,不管之前怎样的兴风作浪。在 Swift 2.0 中,Apple 提供了 defer 关键字,让我们可以实现同样的效果。

    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 机制。

    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 语句,他们在执行的顺序会和栈一样,最后一个进,第一个出。

2、Defer 示例

  • 我们再来看一个 I/O 的示例

    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 来解决这个问题。

    func writeSomething() {
    
        let file = OpenFile()
    
        defer {
            closeFile(file)
        }
    
        let ioStatus = fetchIOStatus()
    
        guard ioStatus != "error" else {
            return
        }
    
        file.write()
    }
    • 我们将 closeFile(file) 放在 defer 代码块里,这样即使 ioStatuserror,在执行 return 前会先执行 defer 里的代码,这样就保证了不管发生什么,最后都会将文件关闭。

以上是关于Swift Defer 延迟调用的主要内容,如果未能解决你的问题,请参考以下文章

ReactiveSwift源码解析 Atomic的代码实现以及其中的Defer延迟Posix互斥锁递归锁

Go中defer的延迟调用

17_defer(延迟调用)关键字的使用

go 延迟函数 defer

Golang Go语言中的 defer 怎么使用?

Golang入门教程(十三)延迟函数defer详解