Где хранится strong-ссылка в Swift и как она управляет памятью?

Ответ

Место хранения: Сама strong-ссылка как переменная хранится в стеке (для локальных переменных) или в куче (если является свойством класса). Объект, на который она указывает, всегда размещается в куче (heap).

Принцип работы (ARC): Strong-ссылка увеличивает счетчик ссылок (retain count) объекта. Пока существует хотя бы одна strong-ссылка, объект не освобождается.

Пример:

class Person {
    let name: String
    init(name: String) { self.name = name }
}
// Создание strong-ссылок
var strongRef1: Person? = Person(name: "Alice") // retain count = 1
var strongRef2 = strongRef1 // retain count = 2 (новая strong-ссылка)

strongRef1 = nil // retain count = 1
strongRef2 = nil // retain count = 0 -> объект деаллоцируется

Ключевые особенности:

  1. По умолчанию: Все ссылки в Swift — strong.
  2. Управление памятью: Автоматическое (ARC). Присваивание увеличивает счетчик, обнуление переменной — уменьшает.
  3. Циклические ссылки: Могут возникнуть, если два объекта имеют strong-ссылки друг на друга. Решаются через weak или unowned.

Ответ 18+ 🔞

А, ну это про наши любимые strong-ссылки, да? Ну слушай, история проще пареной репы, но если не врубиться — потом циклическая зависимость накроет твой проект медным тазом, и будешь рыдать, как Герасим над Муму.

Вот смотри, представь себе объект в памяти — это как квартира в новостройке. Strong-ссылка — это твой договор аренды, оформленный у нотариуса, с печатями, блядь. Пока этот договор лежит у тебя в столе (то есть переменная существует), квартира (объект) твоя, и сносить её никто не имеет права. Сделал копию договора — отдал жене? Отлично, теперь у объекта два законных владельца. Пока хоть один держит свою копию, объект живёт.

Где этот договор-ссылка валяется? Да где угодно! Если переменная локальная — в стопке, на стеке, как чек из магазина. Если это свойство какого-нибудь жирного класса — то уже в куче, в сейфе. Но, внимание, ёпта! Сама квартира, сам объект — он ВСЕГДА в куче. На стеке только бумажки с адресом.

Как работает их чёрная магия (ARC)? Очень просто, блядь. У каждой квартиры (объекта) есть счётчик жильцов. Создал strong-ссылку — заселил одного жильца, счётчик: 1. Скопировал ссылку в другую переменную — заселил второго, счётчик: 2. Обнулил одну переменную — один жилец съебал, счётчик: 1. Обнулил последнюю — квартира пуста, счётчик: 0, и тут же приезжает бульдозер памяти и сравнивает объект с землёй. Деаллокация, пиздец.

Вот, смотри на живом примере, как эти мудаки-жильцы заселяются и выселяются:

class Person {
    let name: String
    init(name: String) { self.name = name }
}
// Создание strong-ссылок
var strongRef1: Person? = Person(name: "Alice") // Жилец 1 заехал. retain count = 1
var strongRef2 = strongRef1 // Тот же мудак дал копию ключа брату. retain count = 2 (новая strong-ссылка)

strongRef1 = nil // Брат съебал, ключ выбросил. retain count = 1
strongRef2 = nil // И второй съебал. retain count = 0 -> объект деаллоцируется, бульдозер нахуй!

А теперь главные фишки, которые в голове держать надо:

  1. По умолчанию они все такие. Объявил var ref = MyClass() — поздравляю, ты только что создал strong-ссылку, даже не зная того. Swift так заботится, сука.
  2. Память сама управляется. ARC — он умный, он считает. Твоя работа — правильно расставлять weak и unowned, когда нужно, чтобы не было пиздеца.
  3. Циклические ссылки — это ад. Это когда две квартиры (объекта) прописаны друг у друга. У Alice в договоре прописан Bob, а у Bob в договоре прописана Alice. Они оба съехали, но договора-то друг на друга остались! Счётчики никогда не станут нулём, и бульдозер памяти никогда не приедет. Мусор, утечка. От этого спасают weak (сосед, у которого есть ключ, но он не жилец) и unowned (сосед, который клянётся, что жилец-то есть, но если его нет — краш, пизда).

Вот и вся наука. Главное — следи, чтобы твои объекты не начали друг друга в strong-объятиях душить, а то приедет ARC, посмотрит на эти циклические пляски и скажет: «Ну, ебать, живите тут вместе вечно, мне похуй». И память потечёт.