Swift下标实现能否设置元组值?

Swift下标实现能否设置元组值?,swift,Swift,我的Swift类正在实现一个协议,其中包括以下(必需)下标: subscript(index: Int) -> (Foo, Bar)? { get set } 这应该允许我打电话,例如: let (foo, bar) = myObject[3] 及 实现getter很容易: subscript(index: Int) -> (Foo, Bar)? { get { // Return a tuple of the values at index in the

我的Swift类正在实现一个协议,其中包括以下(必需)下标:

subscript(index: Int) -> (Foo, Bar)? { get set }
这应该允许我打电话,例如:

let (foo, bar) = myObject[3]

实现getter很容易:

subscript(index: Int) -> (Foo, Bar)? {
    get {
        // Return a tuple of the values at index in the Foos and Bars arrays.
        do {
            try return (Foos[index], Bars[index])
        } catch {
            return nil
        }
    }
}
然而,实现setter似乎是不可能的,因为如果
newValue
是一个元组,则无法获取自动生成的
newValue
的“成员”

    set(newValue) {
        Foos[index] = newValue.foo    // No can do.
        Bars[index] = newValue.bar    // No can do.
    } 
我尝试将
newValue
强制转换为元组类型,如下所示:

    set(newValue) {
        if let (track, trackNumber) = newValue as! (SongVersion, TrackNumber) { ... }
    }
但是编译器抱怨说
newValue
不是一个
可选的
,所以它不能被强制转换


在我看来,如果这种下标是不可设置的,那么当您试图重载
下标
以返回元组时,编译器应该抱怨。我遗漏了什么?

是的,下标方法可以有元组类型

首先,您已将
下标
值定义为可选值
(Foo,Bar)?
,因此需要展开
newValue
。(你必须 决定如果
newValue
nil
该怎么办)

第二,如果你愿意的话 要通过名称
.foo/.bar
访问元组成员,必须定义命名元组:

subscript(index: Int) -> (foo: Foo, bar: Bar)? {
    // ...

    set(newValue) {
        if let value = newValue {
            foos[index] = value.foo
            bars[index] = value.bar
        }
    }
}

或者,使用
value.0
value.1
访问元组成员,谢谢!我试着命名元组的参数,但随后我按原样访问它们,而不是作为newValue的命名成员。我还尝试使用0和1,但我在它们前面加了一个美元符号,就好像我在一个代码块中一样,显然这也不起作用。我只是尝试了你的实现,在它编译时,我现在得到一个错误,我的类不符合协议,协议要求类型(Int)->(Foo,Bar)?我有不匹配的类型(Int)->(foo:foo,bar:bar)?现在我来试试你的第二个建议。好吧,这很奇怪。在newValue上使用.0和.1会导致类型不一致,因为它们被视为字符串。但是,如果我在协议的定义中添加元组参数la s,则第一种方法有效。@NRitH:协议中要求的类型和下标方法的返回类型必须相同,都是
(Foo,Bar)
,或者都是
(Foo:Foo,Bar:Bar)
。使用
.0
.1
访问元组成员在两种情况下都有效,但
.foo
.bar
仅在第二种情况下有效。
subscript(index: Int) -> (foo: Foo, bar: Bar)? {
    // ...

    set(newValue) {
        if let value = newValue {
            foos[index] = value.foo
            bars[index] = value.bar
        }
    }
}