Swift:布尔值对于类的所有实例保持不变,尽管在for循环中进行了赋值



我有一个以下数组:

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结构来解决这个问题。

然而,不确定确切的理由在起作用。

最新更新