guard & defer

Swift 2.0 带来了两个新的能够简化程序和提高效率的控制流表达形式:guard 和 defer。前者可以让代码编写更流畅,后者能够让执行推迟。

guard

guard 是一个要求表达式的值为 true 从而继续执行的条件语句。如果表达式为 false,则会执行必须提供的 else 分支。

func sayHello(numberOfTimes: Int) {
    guard numberOfTimes > 0 else {
        return
    }
}

使用 guard 来避免过多的缩进和错误

使用if可能在大段代码之后才写到异常情况,而使用guard每一个错误都在相应的检查之后立刻被抛出(尽早返回错误),使代码可读性更高。

不要在 guard 中双重否定

不要滥用这个新的流程控制机制——特别是在条件表达式已经表示否定的情况下。

举个例子,如果你想要在一个字符串为空是提早退出,不要这样写:

guard !string.isEmpty else {
    return
}

defer

Swift 鼓励用尽早返回错误来代替嵌套 if 的处理方式。尽早返回让处理更清晰了,但是已经被初始化(可能也正在被使用)的资源必须在返回前被处理干净。

defer 关键字为此提供了安全又简单的处理方式:声明一个 block,当前代码执行的闭包退出时会执行该 block。

经常 defer

如果在同一个作用域内使用多个 defer 语句,它们会根据出现顺序反过来执行——像栈一样。这个反序是非常重要的细节,保证了被延迟的代码块创建时作用域内存在的东西,在代码块执行同样存在。

    func test(){
        defer {
            print(3)
        }
        
        defer {
            defer {
                print(2)
            }
            print(1)
        }
        
        defer {
            print(4)
        }
    }

打印结果:4
1
2
3
注:嵌套defer先执行外层,后执行内层。

正确 defer

如果在 defer 语句中引用了一个变量,执行时会用到变量最终的值。换句话说:defer 代码块不会捕获变量当前的值。

仔细 defer

另一件需要注意的事情,那就是 defer 代码块无法跳出它所在的作用域。因此如你尝试调用一个会 throw 的方法,抛出的错误就无法传递到其周围的上下文。

func burnAfterReading(file url: URL) throws {
    defer { try FileManager.default.removeItem(at: url) }
    //  Errors not handled

    let string = try String(contentsOf: url)
}

作为替代,你可以使用 try? 来无视掉错误,或者直接将语句移出 defer 代码块,将其放到函数的最后,正常的执行。

你可能感兴趣的:(guard & defer)