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调用将为 range 中的 80 个整数中的每一个调用一次闭包0..<80,这将导致实例化 80 个不同的鞋类对象。

有用的背景

Array(repeating:_count:_)按值获取其参数(注意没有inout)。因此,当您调用它时,您作为参数传递给repeating参数的任何内容都会被复制。

对于类,“复制”需要对完全相同的堆分配对象进行新的引用。它通常也保留在进程中(将其引用计数增加 1),但这在这里并不重要。因此,当您调用 时Array(repeating: ShoeInfo(), count: 80),只创建了一个ShoeInfo实例,然后代码将其复制了 80 次,这意味着它对同一个实例进行了 80 次复制引用。

对于结构,“复制”需要按成员方式完全复制它们。当您尝试 时Array(repeating: ShoeInfoAsAStruct(), count: 80),您将创建一个ShoeInfoAsAStruct(),然后将其复制到阵列的 80 个插槽中的每一个中,从而产生 80 个完整副本。您最终会得到 80 个不同的副本,每个副本都可以单独编辑。这就是为什么切换到struct工作。


以上是Swift:尽管在for循环中进行了赋值,但所有类实例的布尔值都保持不变的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>