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

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

    print("All good")
}

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


当前回答

它确实使具有多个查找和可选项的序列流更加简洁和清晰,并减少了大量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)}

看看能不能坚持下去。

其他回答

一个好处是消除了大量嵌套的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)}

看看能不能坚持下去。

用保护我们的意图是明确的。如果这个特定条件不满足,我们就不想执行其余的代码。 在这里我们也可以扩展链,请看看下面的代码:

guard let value1 = number1, let value2 = number2 else { return }
 // do stuff here

何时使用警卫

如果你有一个带有一些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创建的变量可以从其块外访问。打开大量的可选项是有用的。