我有一个以下数组:
var shoes = Array(repeating: ShoeInfo(), count: 80)
其中ShoeInfo
定义如下:
class ShoeInfo {
var expressionOn: Bool?
var volumeControl: Bool?
var channel: Int?
}
我有一个for
循环:
for i in 0..<16 {
if cond {
shoeArray[i].expressionOn = true
} else {
shoeArray[i].expressionOn = false
}
}
从本质上讲,for
循环中分配的最后一个值将成为shoes
数组中每个类实例的值!
我显然不想这样。有人知道怎么解决这个问题吗?
发生了什么
你只举了一个例子。然后,您创建了一个数组,其中包含对该实例的80个引用。自己看看,试试:
for shoe in shoes {
print(ObjectIdentifier(shoe))
}
您将看到所有引用都指向一个奇异对象。
你可能在寻找什么
这是吗
let shoes = (0..<80).map { _ in ShoeInfo() }
map
调用将为范围0..<80
中的80个整数中的每一个调用闭包一次,这将导致实例化80个不同的鞋对象。
有益的背景
Array(repeating:_count:_)
按值取其参数(注意没有inout
(。因此,当您调用它时,作为参数传递给repeating
参数的任何内容都会被复制。
对于类;复制";需要对完全相同的堆分配对象进行新的引用。它通常也会保留在这个过程中(将其引用计数增加一(,但这在这里并不重要。因此,当您调用Array(repeating: ShoeInfo(), count: 80)
时,只生成了一个ShoeInfo
实例,然后代码将其复制了80次,这意味着它对同一个实例进行了80次复制引用。
对于structs;复制";就成员而言,需要完全复制它们。当您尝试Array(repeating: ShoeInfoAsAStruct(), count: 80)
时,您将创建一个ShoeInfoAsAStruct()
,然后将其复制到阵列的80个插槽中的每个插槽中,从而产生80个完整副本。最后会有80个不同的副本,每个副本都可以单独编辑。这就是为什么切换到struct
有效的原因。
我通过将shoeInfo类更改为shoeInfo结构来解决这个问题。
然而,不确定确切的理由在起作用。