Swift 2引入了guard关键字,它可以用来确保各种数据配置就绪。我在这个网站上看到的一个例子演示了一个submitTapped函数:

func submitTapped() {
    guard username.text.characters.count > 0 else {
        return
    }

    print("All good")
}

我想知道使用guard与使用if条件的老式方法是否有任何不同。它是否提供了简单支票无法获得的好处?


当前回答

和if语句一样,guard也根据表达式的布尔值执行语句。与if语句不同,guard语句只在条件不满足时运行。您可以将守卫更像Assert,但是可以优雅地退出,而不是崩溃。

请参考: http://ericcerney.com/swift-guard-statement/

其他回答

一个好处是消除了大量嵌套的if let语句。请在15:30左右观看WWDC“Swift新功能”视频,其中一节名为“末日金字塔”。

它确实使具有多个查找和可选项的序列流更加简洁和清晰,并减少了大量if嵌套。参见Erica Sadun关于替换if的帖子. ....可能会忘乎所以,下面是一个例子:

    let filteredLinks = locationsLinkedToList.filter({$0.actionVerb == movementCommand})
    guard let foundLink = filteredLinks.first else {return ("<Person> cannot go in that direction.", nil, nil)}
    guard filteredLinks.count == 1 else {return ("<Person> cannot decide which route to take.", nil, nil)}
    guard let nextLocation = foundLink.toLocation else {return ("<Person> cannot go in that direction.", nil, nil)}

看看能不能坚持下去。

简单地说,它提供了一种在执行之前验证字段的方法。这是一种很好的编程风格,因为它增强了可读性。在其他语言中,它可能是这样的:

func doSomething() {
    if something == nil {
        // return, break, throw error, etc.
    }
    ...
}

但是因为Swift为你提供了可选项,我们不能检查它是否为nil并将其值赋值给一个变量。相反,if let检查它不是nil,并分配一个变量来保存实际值。这就是警卫发挥作用的地方。它为您提供了一种更简洁的方式,可以使用可选项提前退出。

何时使用警卫

如果你有一个带有一些UITextField元素或一些其他类型的用户输入的视图控制器,你会立即注意到你必须展开textField。文本可选,以获得内部的文本(如果有!)。isEmpty在这里不会有任何好处,没有任何输入,文本字段将简单地返回nil。

因此,你有一些这样的东西,你将它们展开并最终传递给一个函数,该函数将它们发布到服务器端点。我们不希望服务器代码必须处理nil值或错误地向服务器发送无效值,因此我们将首先使用guard打开这些输入值。

func submit() {
    guard let name = nameField.text else {
        show("No name to submit")
        return
    }

    guard let address = addressField.text else {
        show("No address to submit")
        return
    }

    guard let phone = phoneField.text else {
        show("No phone to submit")
        return
    }

    sendToServer(name, address: address, phone: phone)
}

func sendToServer(name: String, address: String, phone: String) {
  ...
}

您会注意到,我们的服务器通信函数以非可选的String值作为参数,因此会提前展开保护。展开有点不直观,因为我们习惯使用if let来展开,它将值展开以在块中使用。这里guard语句有一个相关联的块,但它实际上是一个else块——也就是说,如果展开失败,你所做的事情——值被直接展开到与语句本身相同的上下文中。

//关注点分离

没有保护

如果不使用guard,我们最终会得到一大堆类似于末日金字塔的代码。这不能很好地扩展向表单添加新字段或使代码非常可读。缩进可能很难遵循,特别是在每个分支上有这么多其他语句。

func nonguardSubmit() {
    if let name = nameField.text {
        if let address = addressField.text {
            if let phone = phoneField.text {
                sendToServer(name, address: address, phone: phone)
            } else {
                show("no phone to submit")
            }
        } else {
            show("no address to submit")
        }
    } else {
        show("no name to submit")
    }
}

是的,我们甚至可以将所有这些语句合并为一个用逗号分隔的语句,但我们将失去找出哪条语句失败并向用户显示消息的能力。

https://thatthinginswift.com/guard-statement-swift/

与if不同,guard创建的变量可以从其块外访问。打开大量的可选项是有用的。