【问题标题】:How do I condense unwrapping multiple optionals in Swift?如何在 Swift 中压缩展开多个选项?
【发布时间】:2015-10-02 11:19:49
【问题描述】:

我想解开这 6 个可选变量,如果它们为空,我想给它们一个空白字符串值。这样我就可以将这些变量打包到发送到 API 的参数数组中。

我仍然是 Swift 的初学者,这是我理解如何实现它的唯一最简单的方法,但我内心的编码人员说这看起来像 **** 一样多余和蹩脚。

有人可以帮我把它浓缩或简化吗?

    if let fbEmail = self.fbEmail {

    }else{
        self.fbEmail = ""
    }

    if let fbDob = self.fbDob {

    }else{
        self.fbDob = ""
    }

    if let fbGender = self.fbGender {

    }else{
        self.fbGender = ""
    }
    if let fbUserIp = self.fbUserIp {

    }else{
        self.fbUserIp = ""
    }
    if let fbFacebookId = self.fbFacebookId {

    }else{
        self.fbFacebookId = ""
    }
    if let fbFacebookAccessToken = self.fbFacebookAccessToken {

    }else{
        self.fbFacebookAccessToken = ""
    }

【问题讨论】:

    标签: swift if-statement


    【解决方案1】:

    只需 6 行代码即可完成:

    self.fbEmail  = self.fbEmail  ?? ""
    self.fbDob    = self.fbDob    ?? ""
    self.fbGender = self.fbGender ?? ""
    self.fbUserIp = self.fbUserIp ?? ""
    self.fbFacebookId = self.fbFacebookId ?? ""
    self.fbFacebookAccessToken = self.fbFacebookAccessToken ?? ""
    

    编辑:?? 语法是怎么回事:这是“如果 nil 分配另一个值”的快捷方式:

    let c = a ?? b
    

    如果a != nil,则分配c = a,否则分配c = b

    【讨论】:

    • 你能解释一下“??”语法以及这里到底发生了什么?
    • 第二次阅读您的代码后,我不确定您要做什么。当self.fbEmail 为nil 或尝试将其值分配给局部变量时,您要为其分配一个空字符串吗?
    • 我正在尝试在 self.fbEmail 为 nil 时为其分配一个空字符串
    • 轻微修正:let c = a ?? b 如果a != nil 将分配c = a!,否则c = b。展开很重要。
    • 不知道那个操作员。好优雅!
    【解决方案2】:

    您一次可以打开多个。但是如果你这样做了,你将无法知道哪一个是 nil。你只会知道有些是 nil 或 none 是。

    除此之外,它们是否都需要是可选的?当它们为 nil 时,你不能用你给它们的默认值来初始化它们吗?


    片段:

    完全避免这个问题。

    // just init with a default value without them being an optional
    var fbEmail : String = ""
    var fbDob : String = ""
    

    nil 的检查替换为.isEmpty

    var string : String = ""
    
    string.isEmpty // returns true
    
    string = "SomeString"
    
    string.isEmpty // returns false
    

    带有起始值的可选。

    // init wit default values while still optional
    var fbEmail : String? = ""
    var fbDob : String? = ""
    

    一次打开​​多个。

    if let unwrfbEmail = fbEmail, let unwrfbDob = fbDob {
        // stuff available here
    } else {
        // handle the error
    }
    
    guard let unwrfbEmail = fbEmail, let unwrfbDob = fbDob else {
        // put return/break here and handle the error
    }
    // stuff available here
    

    所有值的容器。它们是可选的,但当设置为 nil 时,它们将重置为默认值。您还可以将它们声明为强制解包选项!。或者使用上面找到的方法一次将它们全部解开。 显然复制粘贴并将didSet更改为所有变量。

    // container stuct that uses didSet to avoid nil and reset to default values
    struct container {
    
        var fbEmail : String? = "" {
            didSet {
                if fbEmail == nil {
                    fbEmail = ""
                }
            }
        }
        var fbDob : String? = ""
        var fbGender : String? = ""
        var fbUserIp : String? = ""
        var fbFacebookId : String? = ""
        var fbFacebookAccessToken : String? = ""
    
    }
    

    【讨论】:

    • 同意;我认为选项应该只用于没有有意义的默认值的变量来初始化它们,或者需要能够标记“未设置”状态。
    • @NicolasMiari 完全同意,你同意我和你的其他观点:) 可能需要它们,因为用于获取值的函数可能返回 nil。在这种情况下使用 didSet 重置为默认值是一个很好的解决方法。
    • 这是一个很棒且非常全面的答案!谢谢R门克。我实际上经历了仅声明初始“”空白值的解决方案,但这会干扰我检查变量是否为可选的其他功能。例如,fbEmail 是一个可选的,我可以默认给它 "",但是 doesEmailExist() 函数不能正常工作,因为它会认为一个空字符串意味着一个电子邮件存在。所以本质上,我认为这些解决方案中的任何一个都不起作用:( Ps。我尝试了“一次解开超过 1 个”,我需要弄清楚某些变量是否不为零:/
    • .isEmpty替换检查nil
    • 哇哦,现在可以了,但有点违背了让它成为可选的目的,对吧?
    猜你喜欢
    • 2019-11-20
    • 1970-01-01
    • 1970-01-01
    • 2018-02-12
    • 2010-11-25
    • 1970-01-01
    • 1970-01-01
    • 2020-12-07
    • 2011-01-28
    相关资源
    最近更新 更多