Структуры и классы: значение против ссылки
И структура, и класс позволяют создавать собственные типы. Но они по-разному ведут себя при копировании, и это различие — одно из важнейших в Swift.
Суть урока: структура копируется по значению (каждая копия независима), класс — по ссылке (все ссылки указывают на один объект). SwiftUI построен на структурах, и понимать разницу нужно с самого начала.
Объявление почти одинаковое — отличается ключевое слово:
struct PointS { var x: Int; var y: Int }
class PointC { var x = 0; var y = 0 }А вот поведение принципиально разное. Структура — тип-значение: присваивание создаёт независимую копию.
var a = PointS(x: 1, y: 1)
var b = a // КОПИЯ
b.x = 99
print(a.x) // 1 — a не изменилсяКласс — тип-ссылка: переменные указывают на один и тот же объект в памяти.
let p = PointC()
let q = p // та же ссылка
q.x = 99
print(p.x) // 99 — изменили общий объектСТРУКТУРА (значение) КЛАСС (ссылка)
a -> [x:1, y:1] p ->\
b -> [x:1, y:1] (копия) -> [x:0, y:0]
q ->/
меняем b -> a не тронут меняем q -> p тоже меняетсяЕщё отличия: только классы поддерживают наследование и имеют идентичность (сравнение через ===). Структуры легче, безопаснее в многопоточности и потому в современном Swift предпочтительны по умолчанию. Apple советует: начинайте со структуры, переходите к классу, только если нужна ссылочная семантика или наследование.
Попробуй сам ▶ — запусти код прямо в браузере (Pyodide). Здесь нет Swift, но логика та же, что под капотом мобильного кода:
# Имитируем разницу: список (изменяемый, как ссылка) vs кортеж/копия.
import copy
struct_like = {'x': 1, 'y': 1}
copy_of = copy.deepcopy(struct_like) # как копия структуры
copy_of['x'] = 99
print('оригинал (значение):', struct_like['x']) # 1
class_like = {'x': 0, 'y': 0}
ref = class_like # та же ссылка (как класс)
ref['x'] = 99
print('оригинал (ссылка):', class_like['x']) # 99Как работает под капотом
Экземпляры структур обычно живут на стеке и копируются целиком при присваивании; благодаря оптимизации copy-on-write большие структуры (массивы, строки) копируют данные только при реальной мутации. Объекты классов живут в куче, и Swift отслеживает их через подсчёт ссылок (ARC): когда последняя ссылка исчезает, память освобождается. Именно ссылочная природа классов делает возможными циклы ссылок и утечки, которых у структур нет.
Частые ошибки
- Ожидать независимости от класса. Изменив объект через одну ссылку, вы меняете его для всех.
- Брать класс по привычке из других языков. В Swift модели данных чаще делают структурами.
- Сравнивать структуры через ===. Оператор идентичности работает только с классами.
Best practices
- По умолчанию выбирайте struct — особенно для моделей данных в SwiftUI.
- Берите class, когда нужна общая изменяемая ссылка, идентичность или наследование.
- Помните: SwiftUI View — это всегда структура.
Итоги. Структуры копируются по значению, классы — по ссылке. Это различие определяет, как данные ведут себя при передаче. Swift и SwiftUI делают ставку на структуры ради безопасности и предсказуемости, и понимание этого выбора — ключ ко всему дальнейшему.
Шире контекста
Выбор между структурой и классом — один из самых частых вопросов на собеседованиях по iOS, и не случайно: он влияет на корректность, производительность и стиль всего кода. Apple даёт ясную рекомендацию: начинайте со структуры и переходите к классу только при явной необходимости — когда нужна общая изменяемая ссылка, идентичность объекта или наследование. В SwiftUI это правило возведено в абсолют: каждое вью — структура, и это не случайно. Лёгкие копируемые значения безопасно создавать и уничтожать тысячами при каждой перерисовке, они не текут памятью и не порождают гонок данных. Классы остаются важны для моделей с долгим жизненным циклом, которые разделяются между экранами, — и именно для них существует макрос @Observable, который мы изучим в разделе про состояние. Понимание разницы значение/ссылка — это тот фундамент, без которого поведение SwiftUI кажется магией, а с ним становится логичным.