【问题标题】:Why are multiple unwrapping optionals impossible?为什么多个展开选项是不可能的?
【发布时间】:2015-01-27 12:56:21
【问题描述】:

我一直在使用 swift 中的选项。我经常使用条件展开模式:

var myOptional: AnyObject?
if let unwrapped = myOptional {
// do stuff
}

但是,有时我有两个可选值,我只想在它们都不是 nil 时使用它们。因此,我尝试使用以下语法:

var myOptional: AnyObject?
var myOtherOptional: AnyObject?
if let unwrapped = myOptional && let otherUnwrapped = myOtherOptional? {
// do stuff
}

我尝试将这两个部分放在括号等中,但似乎没有办法做到这一点。我不能这样做有充分的理由吗?显然,我可以将一个语句嵌入到另一个语句中,但我更愿意将它们全部放在一行中。

【问题讨论】:

标签: swift if-statement optional


【解决方案1】:

Swift 1.2 开始,您可以解开多个选项和条件。

“if let”结构已扩展为允许测试多个 单个 if(或 while)语句中的选项和保护条件 使用类似于通用约束的语法: 如果让 a = foo(), b = bar() 其中 a

【讨论】:

    【解决方案2】:

    因为语言不支持。

    the document:

    if 语句中任何条件的值必须具有符合BooleanType 协议的类型。条件也可以是一个可选绑定声明,如Optional Binding 中所述。

    condition 必须是“BooleanType 的表达式”或“可选绑定声明”。 而且“可选绑定声明”不是“表达式”,所以你不能加入&&

    相反,您可以使用switch

    switch (myOptional, myOtherOptional) {
    case let (.Some(unwrapped), .Some(otherUnwrapped)):
        // do stuff
        println("\(unwrapped), \(otherUnwrapped)")
    default:
        break
    }
    

    【讨论】:

    【解决方案3】:

    唯一的方法是嵌套 if 语句。我认为这是因为苹果将其实现为syntactic sugar。所以预编译器会转换

    var myOptional: AnyObject?
    if let unwrapped = myOptional {
        // do stuff
    }
    

    进入

    var myOptional: AnyObject?
    if myOptional != nil {
        let unwrapped = myOptional
        // do stuff
    }
    

    您当然可以在单个 if 中自己完成此操作,但这只会使您的代码更漂亮一点。不利的一面是,您在调试时不知道是哪一个导致了崩溃。

    欲了解更多信息,请参阅documentation

    【讨论】:

    • “所以预编译器将 ... 转换为 ...” – 我不这么认为(而且我认为 Swift 编译器甚至不使用预编译器)。事实上,这两个代码块在线程安全方面并不是 100% 等效的。
    • @MartinR 好吧,正如我所说的“我认为”,遗憾的是我没有找到任何支持或削弱这一说法的证据。无论如何,它可以作为编译过程的一部分来完成。当您拥有 AST(抽象语法树)时,这很容易做到。但老实说,我不知道苹果在那里做什么,我只是猜测。
    • @MartinR 关于线程安全,如果你在一行中写了一些东西,并不意味着它就是线程安全的。所以第一个选项仍然可能不是线程安全的。
    【解决方案4】:
        var myOptional: AnyObject?
        var myOtherOptional: AnyObject?
        let unwrapped: AnyObject? = myOptional,  otherUnwrapped: AnyObject? = myOtherOptional?
        if (unwrapped != nil && otherUnwrapped != nil) {
           // Do Stuff 
        }
    

    这是您可以做到的另一种方式。 Swift 看起来一天比一天好

    【讨论】:

      猜你喜欢
      • 2018-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多