У меня есть следующий массив:

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!

Я явно этого не хочу. Кто-нибудь знает, как это исправить?

1
Cheetaiean 21 Май 2021 в 01:15

2 ответа

Лучший ответ

Что случилось

Вы сделали только один экземпляр. Затем вы создали массив, содержащий 80 ссылок на этот единственный экземпляр. Убедитесь сами, попробуйте:

for shoe in shoes {
    print(ObjectIdentifier(shoe))
}

Вы увидите, что все ссылки указывают на единственный объект.

Что вы, вероятно, ищете

Это:

let shoes = (0..<80).map { _ in ShoeInfo() }

Вызов map вызовет закрытие один раз для каждого из 80 целых чисел в диапазоне 0..<80, что вызовет создание 80 различных объектов обуви.

Полезный фон

Array(repeating:_count:_) принимает свои параметры по значению (обратите внимание, что нет inout). Таким образом, когда вы его вызываете, все, что вы передаете в качестве аргумента для параметра repeating, копируется.

Для классов «копирование» влечет за собой создание новых ссылок на тот же самый объект, выделенный в куче. Он также обычно сохраняется в процессе (увеличивая количество ссылок на единицу), но здесь это не важно. Таким образом, когда вы вызывали Array(repeating: ShoeInfo(), count: 80), был создан только один экземпляр ShoeInfo, и затем код скопировал его 80 раз, то есть он сделал 80 скопированных ссылок на один и тот же экземпляр.

Для структур "копирование" влечет за собой их полное копирование по частям. Когда вы попробуете Array(repeating: ShoeInfoAsAStruct(), count: 80), вы создадите один ShoeInfoAsAStruct(), который затем будет скопирован в каждый из 80 слотов массива, в результате чего получится 80 полных копий. В итоге вы получаете 80 отдельных копий, каждую из которых вы можете редактировать отдельно. Вот почему переключение на struct сработало.

6
Alexander 20 Май 2021 в 22:36

Я решил это, изменив класс shoeInfo на структуру shoeInfo.

Однако не уверен в точном объяснении.

-1
Cheetaiean 20 Май 2021 в 22:18