Объекты и ссылки
Суть
В классическом ООП «объект» почти всегда означает ссылочный тип: переменная хранит адрес, несколько переменных могут указывать на один объект, изменение через одну видно через другую. В Swift это только половина картины: есть reference types (class, actor, замыкания) и value types (struct, enum, кортежи), и выбор между ними — ключевое проектное решение.
Пример
final class Node { var value: Int; init(_ v: Int) { value = v } }
struct Point { var x: Int }
let n1 = Node(1)
let n2 = n1 // same object, retain count 2
n2.value = 42
print(n1.value) // 42 — shared state
print(n1 === n2) // true — identity, not equality
var p1 = Point(x: 1)
var p2 = p1 // independent copy
p2.x = 42
print(p1.x) // 1
final class Parent { var child: Child? }
final class Child { weak var parent: Parent? } // breaks the cycle
let parent = Parent()
parent.child = Child()
parent.child?.parent = parent
Ссылочные типы
- Имеют identity:
===сравнивает адреса,==— содержимое (если типEquatable). - Живут под ARC: каждая сильная ссылка увеличивает счётчик; объект освобождается при нуле. Два объекта, держащие друг друга сильно, — retain cycle, утечка. Разрывается
weak(Optional, обнуляется) илиunowned(не Optional, crash при обращении к освобождённому объекту). letу класса фиксирует ссылку, но не содержимое:let node = Node(1); node.value = 2— допустимо.
Значимые типы
- Копируются при присваивании и передаче;
letделает значение полностью неизменяемым;mutatingпомечает методы, меняющиеself. - Нет identity и нет ARC-накладных расходов для «чистых» структур (структура с полем-классом всё равно делает retain/release на копии).
- Большие структуры (
Array,String) используют copy-on-write, поэтому копия дёшева.
На что смотрит интервьюер
- Когда class: нужна identity, общее изменяемое состояние, наследование от UIKit, объект с жизненным циклом (
deinit). - Когда struct: данные, модели, DTO, всё, что должно быть
Sendableбез усилий. - Замыкания — тоже ссылочные типы: захват
selfв escaping-замыкании создаёт сильную ссылку; отсюда[weak self].