Copy-on-Write
Copy-on-Write (COW) это механизм оптимизации, который используют коллекции (и не только) Swift. Такие типы могут хранить много данных, поэтому при присваивании другой переменной данные сразу не копируют. Настоящая копия появится именно в момент изменения одной из переменных.
Collections defined by the Swift standard library like arrays, dictionaries, and strings use an optimization to reduce the performance cost of copying. Instead of making a copy immediately, these collections share the memory where the elements are stored between the original instance and any copies. If one of the copies of the collection is modified, the elements are copied just before the modification. The behavior you see in your code is always as if a copy took place immediately.
Происходит это потому, что коллекции хоть и value type, и сами лежат на стеке, данные у них живут в куче. Переменная только ссылается на эти данные. При присваивании копируется переменная, а не содержимое в куче.

Какие value type поддерживают copy-on-write
Из документации мы видим, что этот механизм есть у коллекций стандартной библиотеки Swift и у String:
Array,ContiguousArray,Dictionary,SetString
Отдельно типы, которые смотрят на те же данные, что и родитель:
ArraySliceSubstring
Из Foundation:
DataAttributedString
Copy-on-Write для кастомных struct
Хоть и не все value type поддерживают copy-on-write, мы можем сделать его в своих struct.
Основным помощником тут станет функция isKnownUniquelyReferenced, которую можно вызвать для экземпляра class. Она проверяет, есть ли на этот экземпляр только одна сильная ссылка.
isKnownUniquelyReferenced(_:)Но как нам её использовать? У нас же value type, какие ещё ссылки? Именно поэтому данные держит не сама структура, а класс внутри неё. Структура это обёртка. Класс живёт в куче. Если ссылка на него не одна, перед изменением структура просит у класса копию.
final class Storage {
var value: Int
init(_ value: Int) { self.value = value }
func copy() -> Storage { Storage(value) }
}
struct CowBox {
private var storage: Storage
init(_ value: Int) {
storage = Storage(value)
}
var value: Int {
get { storage.value }
mutating set {
if !isKnownUniquelyReferenced(&storage) {
storage = storage.copy()
}
storage.value = newValue
}
}
}
var a = CowBox(1)
var b = a // шейрят один Storage
print(a.value, b.value) // 1 1
b.value = 99 // copy(), потом запись
print(a.value, b.value) // 1 99