在一些语言中,有 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
里的代码,这样就保证了无论发生什么,最后都会将文件关闭。