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

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

    print("All good")
}

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


当前回答

阅读这篇文章,我注意到使用Guard的巨大好处

下面你可以用一个例子来比较guard的用法:

这是没有防备的部分:

func fooBinding(x: Int?) {
    if let x = x where x > 0 {
        // Do stuff with x
        x.description
    }

    // Value requirements not met, do something
}

在这里,您将所需的代码放在所有条件中 您可能不会立即发现这有什么问题,但是您可以想象,如果它嵌套了许多在运行语句之前都需要满足的条件,那么它会变得多么令人困惑

解决这个问题的方法是首先进行每一项检查,如果有任何不符合就退出。这样可以很容易地理解什么条件将使该函数退出。

但是现在我们可以使用guard,我们可以看到它可以解决一些问题:

func fooGuard(x: Int?) {
    guard let x = x where x > 0 else {
        // Value requirements not met, do something
        return
    }

    // Do stuff with x
    x.description
}

检查你想要的条件,而不是你不想要的条件。这同样类似于断言。如果条件不满足, 运行Guard的else语句,跳出函数。 如果条件通过,这里的可选变量将自动在保护的范围内为您展开 语句被调用——在本例中是fooGuard(_:)函数。 您可以尽早检查坏的情况,使您的函数更易于阅读和维护

同样的模式也适用于非可选值:

func fooNonOptionalGood(x: Int) {
    guard x > 0 else {
        // Value requirements not met, do something
        return
    }

    // Do stuff with x
}

func fooNonOptionalBad(x: Int) {
    if x <= 0 {
        // Value requirements not met, do something
        return
    }

    // Do stuff with x
}

如果你还有任何问题,你可以阅读整篇文章:Swift guard声明。

结束

最后,通过阅读和测试,我发现如果你使用guard来打开任何可选选项,

这些未包装的值将保留在您的其余部分中使用 代码块

.

guard let unwrappedName = userName else {
    return
}

print("Your username is \(unwrappedName)")

在这里,打开的值只在if块中可用

if let unwrappedName = userName {
    print("Your username is \(unwrappedName)")
} else {
    return
}

// this won't work – unwrappedName doesn't exist here!
print("Your username is \(unwrappedName)")

其他回答

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

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

阅读这篇文章,我注意到使用Guard的巨大好处

下面你可以用一个例子来比较guard的用法:

这是没有防备的部分:

func fooBinding(x: Int?) {
    if let x = x where x > 0 {
        // Do stuff with x
        x.description
    }

    // Value requirements not met, do something
}

在这里,您将所需的代码放在所有条件中 您可能不会立即发现这有什么问题,但是您可以想象,如果它嵌套了许多在运行语句之前都需要满足的条件,那么它会变得多么令人困惑

解决这个问题的方法是首先进行每一项检查,如果有任何不符合就退出。这样可以很容易地理解什么条件将使该函数退出。

但是现在我们可以使用guard,我们可以看到它可以解决一些问题:

func fooGuard(x: Int?) {
    guard let x = x where x > 0 else {
        // Value requirements not met, do something
        return
    }

    // Do stuff with x
    x.description
}

检查你想要的条件,而不是你不想要的条件。这同样类似于断言。如果条件不满足, 运行Guard的else语句,跳出函数。 如果条件通过,这里的可选变量将自动在保护的范围内为您展开 语句被调用——在本例中是fooGuard(_:)函数。 您可以尽早检查坏的情况,使您的函数更易于阅读和维护

同样的模式也适用于非可选值:

func fooNonOptionalGood(x: Int) {
    guard x > 0 else {
        // Value requirements not met, do something
        return
    }

    // Do stuff with x
}

func fooNonOptionalBad(x: Int) {
    if x <= 0 {
        // Value requirements not met, do something
        return
    }

    // Do stuff with x
}

如果你还有任何问题,你可以阅读整篇文章:Swift guard声明。

结束

最后,通过阅读和测试,我发现如果你使用guard来打开任何可选选项,

这些未包装的值将保留在您的其余部分中使用 代码块

.

guard let unwrappedName = userName else {
    return
}

print("Your username is \(unwrappedName)")

在这里,打开的值只在if块中可用

if let unwrappedName = userName {
    print("Your username is \(unwrappedName)")
} else {
    return
}

// this won't work – unwrappedName doesn't exist here!
print("Your username is \(unwrappedName)")

它确实使具有多个查找和可选项的序列流更加简洁和清晰,并减少了大量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语句一样,guard也根据表达式的布尔值执行语句。与if语句不同,guard语句只在条件不满足时运行。您可以将守卫更像Assert,但是可以优雅地退出,而不是崩溃。

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