首页 > 解决方案 > 人们如何处理迭代 Swift 结构值类型属性?

问题描述

这是人们必须一直出现的明显情况:

struct Foundation {
    var columns : [Column] = [Column(), Column()]
}
struct Column : CustomStringConvertible {
    var cards = [Card]()
    var description : String {
        return String(describing:self.cards)
    }
}
struct Card {}
var f = Foundation()
for var c in f.columns {
    c.cards.append(Card())
}

该代码是合法的,但它当然对 没有影响f,因为var c它仍然是一个副本——实际columnsf不受影响。

我没有任何困难理解为什么会发生这种情况。我的问题是人们通常会怎么做

显然,我可以通过将 Column 声明为class而不是struct来解决整个问题,但人们通常会这样做吗?(我试图遵循一种心理限制,即当不需要动态调度/多态性/子类化时,应该避免使用类;也许我把它带得太远了,或者人们通常会做其他事情,比如以inout某种方式使用。)

标签: swiftfor-loopstructpass-by-value

解决方案


从 Swift 4 开始,一种折衷方案是迭代可变集合的索引而不是元素本身,这样

for elem in mutableCollection {
    // `elem` is immutable ...
}

或者

for var elem in mutableCollection {
   // `elem` is mutable, but a _copy_ of the collection element ...
}

变成

for idx in mutableCollection.indices {
    // mutate `mutableCollection[idx]` ...
}

在您的示例中:

for idx in f.columns.indices {
   f.columns[idx].cards.append(Card()) 
}

正如@Hamish 在评论中指出的那样,未来版本的 Swift 可能会实现mutating iteration,使得

for inout elem in mutableCollection {
   // mutate `elem` ...
}

可能的。


推荐阅读