在Swift中,如何压缩解包多个可选项?

4
我想要解包这6个可选变量,如果它们是null,我希望给它们一个空字符串值。这样我可以将这些变量打包成参数数组发送给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 = ""
    }
2个回答

8
您可以只用六行代码来实现这个功能:
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


能否请您解释一下"??"语法,以及这里到底发生了什么? - trixmasta
谢谢!这正是我在寻找的。 - trixmasta
1
稍作更正:如果 a != nil,则 let c = a ?? b 将会赋值为 c = a!,否则 c = b。解包是很重要的。 - vacawama
1
不知道这个运算符。太优美了! - R Menke
?? 运算符在 Swift 文档中被称为 Nil Coalescing Operator - Maic López Sáenz
显示剩余3条评论

4
你可以同时取消多个选项。但是如果这样做,你将无法知道哪一个是 nil。你只会知道某些可能是 nil 或者全部都不是。
除此之外,它们都需要是可选的吗?当它们为 nil 时,你不能用默认值来初始化它们吗?
代码片段:
干脆避免这个问题。
// just init with a default value without them being an optional
var fbEmail : String = ""
var fbDob : String = ""

.isEmpty 替换对 nil 的检查。

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? = ""

}

同意;我认为可选项应该仅用于那些没有有意义的默认值可以初始化它们,或者需要能够标记“未设置”状态的变量。 - Nicolas Miari
@NicolasMiari 完全同意,你同意我的观点并提出了其他观点 :) 这些可能是必要的,因为用于获取值的函数可能返回nil。在这种情况下使用didSet重置为默认值是一个不错的解决方法。 - R Menke
这是一个非常好而且全面的答案!谢谢R Menke。我实际上已经尝试了声明一个初始的""空值的解决方案,但是那会干扰到其他检查变量是否可选的函数。例如,fbEmail是可选的,我可以默认给它"",但是doesEmailExist()函数将无法正确工作,因为它会认为空字符串意味着存在电子邮件。所以基本上,我认为这些解决方案都不起作用:(顺便说一句,我尝试了“一次展开多个”,我需要弄清楚某些变量是否为nil :/ - trixmasta
1
.isEmpty 替换检查 nil - R Menke
哦,现在这样做可以行,但有点违背了一开始将其设为可选项的初衷,对吧? - trixmasta
正是因为这个原因,我才建议这样做 ;) - R Menke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接