使用guard检查nil而不隐式展开

问题描述 投票:4回答:2

我知道周围有一些类似的问题,但我找不到一个特定的问题。我有一个请求,我想检查是否存在error密钥。它不存在一切都很好,如果不是我应该处理错误。目前,我实现如下:

if let error = json["error"] {
    // handle error
}
else {
    // handle success
}

我想在这里使用一个保护声明来使成功案例没有缩进。我想出的唯一方法是

guard json["error"] == nil else {
    let error = json["error"]!
    // handle error
} 

// handle success

但这对我来说似乎不对!还有其他方法吗?

swift
2个回答
7
投票

在你的guard代码中,你必须在else块中有一个return语句。像这样...

guard json["error"] == nil else {
    let error = json["error"]!
    // handle error
    return
}

// handle success

但你是对的。必须强制打开错误并不理想。

所以在这种情况下。我认为guard是错误的解决方案。而是使用if但从条件块返回。这消除了使用else块的需要。

if let error = json["error"] {
    print(error)
    // handle error
    return
}

// handle success...
// no need for else block. Just return from the if in the error case.

guard letif let之间的区别在于未打开的可选范围。

如果挡板位于挡块内,则挡板位于挡块外。


1
投票

在Swift Evolution邮件列表中提出了您的问题的想法:

“守卫不让”任意绑定

https://forums.swift.org/t/idea-guard-not-let-optional-binding/2614

你想要检查一个可选项是否为n,并且如果不是(可能使用你现在知道的值存在)仍然保释,这是相当普遍的,例如:

guard cachedValue == nil else { return cachedValue! } cachedValue = //… expensive calculation

在检查Optional.Some时,我们有这个可爱干净的let语法似乎有点“不公平”,但我们必须在检查Optional.None时对nil和显式解包进行这种丑陋的手动检查。实际上没有其他方法来满足守卫声明;我们的可选绑定只能单向无法评估。

不幸的是,Swift中当前不存在该构造。

替代方案是稍微笨拙/重复的guard语法,可能有一个force-unwrap:

guard json["error"] == nil else {
    return json["error"]!
}

或使用if-let(不强制范围退出,如guard):

if let error = json["error"] {
    return error
}
© www.soinside.com 2019 - 2024. All rights reserved.