【问题标题】:How is Swift IF LET evaluated?Swift IF LET 如何评估?
【发布时间】:2014-09-13 22:23:17
【问题描述】:

我在 Swift 网站和这里的各种帖子上看到了这段代码,我正在努力掌握基本知识。这条线是如何评估的?

if let name = optionalName {

我很困惑,因为它不是名称 == 可选名称,它正在分配值,那么它如何报告真实和 为什么当你用 nil 替换 john appleseed 时它不是真的,因为它仍然是相等的?

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

【问题讨论】:

标签: if-statement swift


【解决方案1】:

基本上这行是说,“如果你可以让新变量name等于optionalName的非可选版本,用它做以下事情”。正如 Martin 所指出的,这称为Optional Binding

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

【讨论】:

  • 当我开始阅读它时,我会阅读它,我只是在快速介绍的开始,它没有解释它。你的解释很有道理,谢谢。
  • 为什么我们不应该使用 "!=" 而不是 "if let" 来检查可选变量是否具有类似的值 - if optionalName != nil { greeting = "Hello, (name)" }
  • @Nuibb 因为在使用if let 时,我们将值绑定到一个非可选变量(本例中为name)。您的示例无法编译,因为现在没有名为 name 的变量。如果您将示例更改为使用optionalName,它将打印为Hello, Optional("John Appleseed")。您可以在检查 nil Hello, \(optionalName!) 后使用强制展开,但如果您将那段代码移动到某处而不进行检查,这更容易出错。
【解决方案2】:

一个可选项是设置或未设置(不是 nil 或 nil)...留给我们一个重要的决定。 “我们应该如何编写我们的代码,以便它可以在两种状态下正常工作?”。我们解包可选的方式决定了我们的选择。

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

  • 崩溃!
  • 将值默认为某个值 — 如果未设置。
  • 优雅地失败,即什么都不做,但也如果设置了值,然后分配它。
  • 优雅地失败,即什么也不做,但是如果值已设置...做某事(它不仅仅是一个单一的任务)。

以下是四种方法


使用forced unwrapping 会崩溃如果你没有价值。如果具有该值至关重要,例如,您会想要这样做。 电影的标题(每部电影都必须有名字)。 ! 用于强制解包。

movieTitle = movie.title!

使用nil coalescing 是另一种为您提供更多控制权的方法,这意味着如果未设置该值,它不会崩溃,如果未设置,它也不会“不设置任何内容”设置......它会做你告诉它做的事情,例如如果没有设置名称,它将默认/设置电影的名称为 untitled_movie?? 用于 nil 合并。

var movieTitle = movie.title ?? "untitled_Movie"

使用optional Chaining 将不会执行任何操作如果您没有值,并且会设置值如果您有一个值。你这样做是因为它的值集是不是至关重要的,例如你的演员的代理人的名字? 用于可选链接。

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,这是optional binding 的两种不同类型)将为您提供更多控制,如果未设置该值也不会崩溃。如果设置了值,那么你可以做一些事情。如果未设置,则可以添加 else 语句。

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

这是最常用的展开方式,因为有些不鼓励强制展开。有关不鼓励使用它的原因的更多讨论,请参阅here。对于guardif-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 上的一些电影没有片名 :)。此外,强制展开意味着您没有进行任何日志记录或断言。那很糟。因为你不知道根本原因是什么。
  • 这是一个稻草人的论点,我从来没有说过“总是使用强制展开”。仅仅因为您不应该在示例中使用强制展开并不意味着在每个示例中都不鼓励强制展开。我给了你一个场景,强制展开是你提出的四个方案中唯一正确的解决方案。您能否为我之前评论所述的场景提供更好的解决方案?如果不是,请考虑修改您关于“强制展开有点不鼓励”的评论,因为不考虑上下文就不会有点不鼓励。
  • 如果您将某些内容默认为“”,那么它不再是可选的
  • 例如,"" 值来自故事板中创建的 UILabel 实例的 text 属性,它是可选的,因为如果您动态创建它可以为 nil,但在这里您不是动态创建它所以它总是包含一个字符串值。在这种情况下,您是否打算不使用强制展开,而是使用 if-let 展开并提供与其默认值“”相同的值?你可以,但那是没有意义的、不必要的和冗长的。如果你使用的 HTTP 库总是会返回一个字典,即使它是一个错误。它取决于上下文。
【解决方案3】:

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

if let name = optionalName {

但不是

if (let name = optionalName) {

Apple documentation(Swift 参考):

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

【讨论】:

    【解决方案4】:

    if 只接受布尔表达式,除了它会抛出错误,所以这段代码 sn-p 说

    if let name = optionalName {
    
    }else{
    
    }
    

    如果 optionalName 为 nil 则条件为 false 并执行 else 语句。但是,如果 optionalName 有一些值,那么可选值将被解包/分配到常量变量中,即名称。

    【讨论】:

      【解决方案5】:

      每当您使用弱引用,可选类型时,最好使用 if let 来保护您的代码并避免崩溃 下面是例子

      var middleName :String? = "some thing"
      if let isExistsMiddleName = middleName {
      // do some thing here
      } else {
      // no middle name
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-03-13
        • 1970-01-01
        • 1970-01-01
        • 2015-02-09
        • 2021-03-15
        • 2010-10-13
        • 1970-01-01
        相关资源
        最近更新 更多