使用元组的Swift可选绑定

15

我试图在Swift中使用元组作为可选绑定的条件语句,但它无法编译,并且错误信息不够明确。为什么以下代码无法编译?

let user:String? = "billy"
let pass:String? = "password"

if let test = (user?,pass?){
    print("this works")
}

或者这个

let user:String? = "billy"
let pass:String? = "password"

if let test = (user,pass){
    print("this works")
}

3
编译器错误是什么?如果我要猜的话,可能是因为创建元组没有可选结果。 - Ian MacDonald
1
你是真的想要绑定元组,还是只想在同一语句中绑定两个可选项?如果是后者,这与使用“if let…”与多个表达式重复了,从Swift 1.2 / Xcode6.3开始有一个简明的解决方案。 - rickster
5个回答

19

编辑:截至Xcode 6.3中的Swift 1.2版本,现在可以执行以下操作:

if let user = user, pass = pass { }

绑定多个未包装的可选值。

您不能以这种方式使用可选的let绑定。let test = (user,pass)将无法编译,因为(user,pass)不是可选项——它是一个包含可选项的元组。也就是说,它是一个(Int?,Int?)而不是一个(Int,Int)?

以下代码可以实现您所需的功能,并允许您同时绑定两个项:

switch (user, pass) {
    case let (.Some(user), .Some(pass)):
        print("this works: \(user), \(pass)")
    default: ()  // must handle all cases
}

你可以在switch语句的case中使用break,即使里面没有代码,这样对我来说更连贯。 - David Berry
1
好观点,可能更好。虽然我从来没有发现自己不需要默认值(事实上,我希望switch语句是表达式,在这种情况下,您必须返回一个有意义的值)。 - Airspeed Velocity
你好。感谢你的建议。".Some()"是什么?它看起来像是一个带有关联值的枚举成员。它是从哪里来的,在这种情况下它是如何工作的? - RMH
你说得很对,那正是它的含义。这就是可选项 - 具有两个情况(Some和None)的枚举类型,并且Some情况具有类型为T的关联值。你甚至可以在标准库中看到它们的定义 - 尝试在playground中键入Optional(5)并cmd-opt-click单词optional。 - Airspeed Velocity
1
提供的答案中缺少了一个let。 它应该是: if let usr = user, let ps = pass { } - BTRUE

7
在Swift 2中,使用可选模式匹配可以编写以下代码:
if case let (user?, pass?) = (user, pass) { }

这在处理存储在变量中的元组(user, pass)时特别有用。

2

正如其他答案所指出的,您必须使用 switch。但是,如果您只需要检查这两个值,则使用没有可选绑定的 if 实际上更短且更容易阅读。

if (user != nil && pass != nil) {
    print("this works: \(user!), \(pass!)")
}
switch 很古怪且难以阅读(摘自另一个答案),但如果你要使用其他情况(nil-some, some-nil, nil-nil),那么它可能是值得的。
switch (user, pass) {
    case let (.Some(user), .Some(pass)): print("this works: \(user), \(pass)")
    default: ()
}

0
if case let (.some(user), .some(pass)) = (optionalUser, optionalPass) {
    print("user \(user). pass \(pass)")
}

如果您添加了代码说明,会更有帮助。 - aheze

-1
假设我们有一个包含两个可选整数的元组。为了解包它,我们可以使用 as? 可选地将其转换为 (Int, Int)。如果其中任何一个是 nil,则无法进行转换。如果成功转换,我们将从该元组中获取已解包的值。
let tuple: (Int?, Int?) = (1, 2)
if let (value1, value2) = tuple as? (Int, Int) {
     print("value1: \(value1), value2: \(value2)")
} 

//value1: 1, value2: 2

1
如果您解释一下提供的代码如何回答问题,那么这将是一个更好的答案。 - pppery

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