TGViewer
ErrorNil. iOS-разработка ErrorNil. iOS-разработка @error_nil · 688 subscribers
Post #524 367
Механизм CoW в Swift

Всем известна простая истина, что в Swift структуры у нас value type, а классы (еще и функции и клоужеры и actor) являются reference type. Все четко.

Про value и reference не буду распинаться, все знают, что это и как работает. Если на пальцах это означает что:


let age: Int = 30


Это у нас value type (Int -> Struct) и value соответственно хранится в стеке.

Справедливо и то, что в следующем коде:

class User {
var name: String
init(name: String){
self.name = name
}
}

let user = User(name: "Superman")


user ссылается на область в куче

class -> reference type -> heap


Пока ничего криминального и все очевидно. Тогда, о чем тут речь?

Допустим у нас есть следующий код:

var justiceLeague: [String] = ["Batmant","Supermen", "Wonder woman"]


justiceLeague - массив, массив это структура

public struct Array<Element>


Соответственно justiceLeague хранится в стеке, так? Ну в целом так-то оно так, но не совсем.

Так как массив может содержать довольно много элементов в Swift (но уверен, что и в некоторых других языках тоже) в качестве оптимизации придумали механизм, который называется Copy on Write или проще CoW. Так в чем же суть и причем тут массивы?

А идея заключается в том, что все коллекции, а это у нас массивы, множества (Set), словари (Dictionary) и строки (String, да, это тоже коллекция, вернее массив из Character) хранятся сами в стеке, как и положено value type, но значения их находятся в куче. Что это значит?

К примеру, возьмём наш исходный массив и скопируем его:

var justiceLeague: [String] = ["Batmant","Supermen", "Wonder woman"]
var suicideSquad = justiceLeague


В данном случае у нас есть две переменные justiceLeague и suicideSquad, по принципам value type у нас происходит копирования из justiceLeague -> suicideSquad и в итоге у них сейчас данные одинаковые, вот в этом и есть камень преткновения.

Дело в том, как я и сказал ранее, для оптимизации решили сделать так, зачем сразу создавать две копии, если мы за весь жизненный цикл программы можем и не поменять данные нашей копии, а вдруг они у нас такими и останутся, поэтому и добавили механизм CoW, название которого и говорит само за себя, Копировать во время Записи. Как это работает?

justiceLeague - хранится в стеке, тут без криминала, но все данные (["Batmant","Supermen", "Wonder woman"]) отправляются в кучу и возвращается указатель на область памяти, откуда мы эти данные можем достать. И когда мы написали


var suicideSquad = justiceLeague


Случилось так, что теперь и justiceLeague и suicideSquad ссылаются на один и тот же участок памяти в куче. Отсюда следует, что у нас на один участок в памяти создано две ссылки.

Но теперь мы хотим изменить данные, что в этом случае происходит.

Допустим мы написали следующий код:

var justiceLeague: [String] = ["Batmant","Supermen", "Wonder woman"]
var suicideSquad = justiceLeague
suicideSquad.append("Green Arrow")


При выполнении suicideSquad.append("Green Arrow") Swift проверяет:

- Если количество ссылок > 1, то данные копируются в новую область кучи и теперь justiceLeague и suicideSquad указывают на разные массивы:

justiceLeague (Стек) -> ["Batmant","Supermen", "Wonder woman"] (Куча)

suicideSquad (Стек) -> ["Batmant","Supermen", "Wonder woman", "Green Arrow"] (Куча)

- Если же, количество ссылок == 1 то мы бы просто изменили массив в куче без копирования.


За проверку ссылок в данном случае отвечает встроенная функция isKnownUniquelyReferenced, которая возращает:
true - если ссылка уникальная
false - если есть и другие владельцы.


func isKnownUniquelyReferenced<T>(_ object: inout T?) -> Bool where T : AnyObject


При помощи этой функции мы можем любую структуру сделать по принципу CoW, вопрос в том, нафига, но такое можно сделать, тут не буду писать код, в целом это распространённое решение, думаю найдете.
  • ❤ 4
  • 🔥 2
More from @error_nil
  1. Oct 9, 2026video post
  2. Oct 9, 2026К слову о том, что происходит
  3. Oct 9, 2026🫠
  4. Oct 7, 2026В общем, никто не просил, но я сделал — добавил мессенджер в своё приложение «Живой?». Ран…
  5. Oct 6, 2026Apple серьезно так поднапряглась с выходом нового айфона
  6. Oct 1, 2026А почему бы и нет? Я тут подумал, что такой формат решает проблему (не то что бы это прям…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →