Swift IF LET如何评估?


86

我已经在Swift网站上看​​到了这段代码,并在这里看到了许多帖子,我试图掌握基础知识。如何评价这条线?

if let name = optionalName {

我很困惑,因为它不是name ==可选名称,而是分配值,那么该报告如何报告为真,以及当您用john appleseed替换为nil时为什么不正确,因为它仍然相等?

var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
if let name = optionalName {
    greeting = "Hello, \(name)"
}

10
在Swift文档中查找“可选绑定” ...
Martin R

3
dev.iachieved.it/iachievedit/?p=314上详细介绍了可选元素,该if let语法称为可选绑定。
2014年

Answers:


100

基本上,这句话说:“如果您可以让新变量name等于非可选版本的optionalName,请执行以下操作”。正如Martin所指出的,这称为Optional Binding

它的唯一目的是测试可选变量是否包含实际值,并将非可选形式绑定到临时变量。这是“解开”可选项或换句话说,访问可选项中包含的值的安全方法。绝不测试任何形式的相等性。它仅测试可选值中是否存在值。


1
当我开始学习它时,我会读到它,我只是在快速介绍的开始,它并没有解释它。您的解释很合理,谢谢。
DeadZero 2014年

1
为什么我们不应该使用“!=”而不是“ if let”来检查可选变量是否具有类似值
-if

4
@Nuibb,因为在使用时,if let我们将值绑定到非可选变量(name在此示例中)。您的示例无法编译,因为现在没有名为的变量name。如果您更改示例以使用optionalName它,则将其打印为Hello, Optional("John Appleseed")。在对nil进行检查之后,可以使用强制展开,Hello, \(optionalName!)但是如果将该代码段未经检查就移动到某个地方,则更容易出错。
drewag '16

29

可选选项是设置的或未设置的(不是nil或nil)...让我们有一个重要的决定。“我们应该如何编写代码,使其在两种状态下都能正常工作?”。我们解包的方式可选项是为我们决定的。

您可以使用多种方法来对抗未设置的可选内容。

  • 崩溃!
  • 将值默认为某些值(如果未设置)。
  • 优雅地失败,即什么也不做,但是如果设置了值,则进行分配。
  • 正常失败,即不执行任何操作,但是,如果设置了该值,则执行某些操作(不止是一次分配)。

以下是4种方法


如果没有值,使用强制展开将导致崩溃。如果具有至关重要的价值,例如电影标题(每部电影都必须有一个名称),则需要这样做。用于强制展开。!

movieTitle = movie.title!

使用nil合并是另一种可以给您更多控制的方法,这意味着如果未设置该值,则不会崩溃;如果未设置该值,则不会“不设置任何内容”……它将按照您的要求进行操作这样做,例如,如果未设置名称,它将默认/将电影名称设置为untitled_movie??用于零合并。

var movieTitle = movie.title ?? "untitled_Movie"

使用可选的链接不会做任何事情,如果你没有一个值,将设定值,如果你有一个值。您这样做的原因是,其价值设定并不是至关重要的,例如,对于演员代理人名字而言?用于可选链接。

let agent = movie.leadActor?.agent //would not crash if you don't have a lead actor (optional chaining)
let agent = movie.leadActor!.agent //would crash if you don't have a lead Actor (forced wrapping)  

使用if-let(或guard这是两种不同类型的可选绑定)将为您提供更多控制权,如果未设置该值,则不会崩溃。如果设置了该值,则可以执行某些操作。如果未设置,则可以添加一条else语句。

if let supportingActor = movie.supportingActor{
print(" The supporting actor is \(supportingActor)}

这是最常用的解包方式,因为不鼓励使用强制解包。有关为什么不鼓励使用它的更多讨论,请参见此处。要在guard和之间进行比较,if-let请参见guard vs. if-let


边注:

可选绑定和可选链接通常一起使用:

if let agent = movie.leadActor?.agent {
ContactInfo = agent.phoneNumber
} // if-let is the optional *binding* part, the movie dot leadActor dot is the optional *chaining*
 

在movieTitle不能为字符串以外的任何东西且所有字符串对movieTitle有效的情况下,为什么不鼓励强制展开?(并且我不希望“无标题的电影”我想要“”)强制展开是这种情况的唯一正确方法,如果您可以删除表示“不建议使用强制展开的部分”,那将是很棒的,因为这是错误的信息。
安迪

假设您打了个网络电话,服务器团队的某个开发人员做出了错误的决定,却忘记发送电影标题。您是否希望您的应用在生产中崩溃?还是只写未知标题?事实上,IMDb上的某些电影没有标题:)。另外,强制展开意味着您还没有进行任何日志记录或断言。那很糟。因为您不知道根本原因是什么。
亲爱的

那是一个稻草人的论点,我从未说过“总是使用强制展开”。仅仅因为您不应该在示例中使用强制展开,并不意味着在每个示例中都不鼓励强制展开。我给了您一个方案,其中强制展开是您提出的四个方案中唯一正确的解决方案。您能为我之前的评论中提到的方案提供更好的解决方案吗?如果不是这样,请考虑修改您对“不鼓励使用强制展开”的评论,因为在不考虑上下文的​​情况下就不鼓励使用。
安迪

如果您将默认值设置为“”,那么它就不再是可选的
Honey,

例如,“”值来自故事板中创建的UILabel实例的text属性,它是可选的,因为如果您动态创建它,则它可以为nil,但是这里不是动态创建的,因此它将始终包含一个字符串值。在这种情况下,您是否不使用强制展开,而是使用if-let展开并提供与其默认值“”相同的值?您可以,但这毫无意义,不必要且冗长。还有,如果您使用的HTTP库即使出现错误也总是返回字典。它取决于上下文。
安迪

4

if语法接受2个不同的条件。第二个是可选绑定,不是布尔值。您可能会这样写,这很令人困惑:

if let name = optionalName {

但不是

if (let name = optionalName) {

Apple文档(Swift参考):

条件的值必须是类型Bool或桥接到的类型Bool。条件也可以是可选的绑定声明,如Optional Binding中所述


3

if 仅采用布尔表达式,否则会引发错误,因此此代码段中的内容

if let name = optionalName {

}else{

}

如果optionalName为nil,则条件为false,否则将执行语句。但是,如果optionalName具有某个值,则将可选值解包/分配给常量变量(即name)。


1

每当您使用弱引用(可选类型)时,最好使用来保护代码并避免崩溃,这是示例

var middleName :String? = "some thing"
if let isExistsMiddleName = middleName {
// do some thing here
} else {
// no middle name
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.