ГлавнаяБлогDeinit и ARC в Swift: как работает подсчёт ссылок
Алгоритмы

Deinit и ARC в Swift: как работает подсчёт ссылок

Узнайте, как Swift автоматически уничтожает классы через ARC и deinit. Практический разбор с примерами кода для iOS-разработчиков.

Al
Редакция Algolitalgolit.ru
8 мин чтения22 июля 2026 г.

Зачем понимать deinit и ARC?

Каждый экземпляр класса в Swift когда-нибудь уничтожается. Но когда именно это происходит? Если вы работаете с классами, рано или поздно столкнётесь с управлением памятью. В этой статье разберём Automatic Reference Counting (ARC) и деинициализатор — механизмы, которые Swift использует, чтобы решить, когда пора «убить» объект. Вы узнаете, как отслеживать создание и уничтожение объектов, и почему let для класса ведёт себя не так, как для структуры.

ARC — невидимый бухгалтер

За каждым экземпляром класса в Swift стоит скрытый счётчик. Каждый раз, когда вы создаёте новую ссылку на класс (присваиваете переменной, передаёте в функцию, кладёте в массив), Swift увеличивает этот счётчик на 1. Когда одна из ссылок исчезает, счётчик уменьшается на 1. Когда счётчик достигает нуля, Swift понимает: на этот объект больше никто не смотрит. Можно безопасно его уничтожить.

Эта система называется Automatic Reference Counting (ARC). Вам не нужно управлять ею вручную — Swift делает это невидимо и непрерывно для каждого экземпляра класса в вашем приложении.

Структурам ARC не нужен, потому что каждая копия структуры — это независимый набор данных. Когда переменная-структура исчезает, данные исчезают вместе с ней. Просто, предсказуемо, без подсчёта.

Классам ARC нужен именно из-за системы «указателей»: несколько переменных могут указывать на одни и те же данные. Без подсчёта ссылок Swift не смог бы узнать, когда последняя ссылка исчезла.

Деинициализатор

Когда счётчик ссылок достигает нуля и экземпляр класса вот-вот будет уничтожен, Swift вызывает специальный метод — деинициализатор, который записывается как deinit. Это противоположность init: если init выполняется при создании экземпляра, то deinit — при уничтожении последней ссылки.

Посмотрим на примере тренировочного лагеря из мира аниме:

class TrainingCamp {
    let name: String
    
    init(name: String) {
        self.name = name
        print("\(name) открылся! 🏕️")
    }
    
    deinit {
        print("\(name) заброшен. Тренировка окончена.")
    }
}

Теперь создадим несколько лагерей и посмотрим, как они уничтожаются:

var camp1: TrainingCamp? = TrainingCamp(name: "Тренировочная база Конохи")
var camp2: TrainingCamp? = TrainingCamp(name: "Лагерь деревни Песка")
var camp3: TrainingCamp? = camp1  // camp1 и camp3 теперь указывают на один лагерь

camp1 = nil  // счётчик ссылок для Конохи падает до 1 (camp3 всё ещё держит)
camp2 = nil  // счётчик для Песка падает до 0 — deinit срабатывает!
camp3 = nil  // счётчик для Конохи падает до 0 — deinit срабатывает!

Вывод:

Тренировочная база Конохи открылся! 🏕️
Лагерь деревни Песка открылся! 🏕️
Лагерь деревни Песка заброшен. Тренировка окончена.
Тренировочная база Конохи заброшен. Тренировка окончена.

Обратите внимание: camp2 запускает деинициализатор сразу после camp2 = nil, потому что это была единственная ссылка. Деинициализатор Конохи не срабатывает до camp3 = nil, так как даже после camp1 = nil счётчик оставался равным 1 благодаря camp3.

Что важно знать о deinit

  • Вы не можете вызвать его сами. deinit вызывается Swift автоматически, когда счётчик ссылок достигает нуля. Вы можете его определить, но не можете запустить вручную.
  • Он не принимает параметры. В отличие от init, deinit не принимает аргументов. Он просто получает сигнал «ты будешь уничтожен, сделай что нужно».
  • Где размещать? Технически — в любом месте класса. Но есть хорошая конвенция: помещать deinit в конец тела класса. Код должен читаться как глава книги, а deinit — это финальная сцена.

Ещё одна особенность: let для классов

Пока мы говорим о различиях классов и структур, стоит упомянуть ещё один нюанс. Если вы создаёте константную структуру через let, то ничего в ней изменить нельзя — ни свойства, ничего. С классами всё иначе. let для класса означает «эта переменная всегда будет указывать на тот же экземпляр». Но это не значит, что сам экземпляр нельзя менять.

class Ninja {
    var powerLevel: Int
    
    init(powerLevel: Int) {
        self.powerLevel = powerLevel
    }
}

let naruto = Ninja(powerLevel: 9000)
naruto.powerLevel = 9001  // ✅ Это можно!
naruto = Ninja(powerLevel: 1)  // ❌ А это нельзя — нельзя переназначить указатель

let naruto означает, что указатель naruto зафиксирован — он всегда будет указывать на тот же экземпляр Ninja. Но данные, на которые указывает указатель, можно менять свободно. Это становится понятным, если вспомнить аналогию с указателем: let фиксирует указатель на месте, но ничего не говорит о том, что находится на другом конце.

Почему это важно в реальной iOS-разработке

ARC и деинициализаторы имеют значение, когда:

  • Вы управляете ресурсами, требующими явной очистки — сетевые соединения, файловые дескрипторы, наблюдатели, таймеры.
  • Вам нужно отлаживать проблемы с памятью и хочется точно знать, когда объекты создаются и уничтожаются.
  • Вы работаете со сложными графами объектов, где множество сущностей держат ссылки на одни и те же данные.

В повседневной SwiftUI-разработке вы не будете писать deinit постоянно. Но понимание того, что он существует и почему он существует (потому что ARC нужен хук для очистки), помогает разобраться в модели памяти вашего приложения, а не просто надеяться, что всё работает.

Практический вывод

Swift подсчитывает, сколько сущностей указывает на каждый экземпляр класса. Когда счётчик достигает нуля, вызывается deinit и объект уничтожается. Вот и вся суть ARC. А let для класса означает постоянство указателя, а не данных — это тот нюанс, который ставит в тупик, пока аналогия с указателем не становится очевидной. 🌸

Попробуйте прямо сейчас добавить deinit в один из ваших классов и понаблюдайте, когда он вызывается. Это лучший способ закрепить понимание ARC.

#ARC#deinit#Swift#управление памятью#классы
Al
Редакция Algolit

Пишем про алгоритмы, подготовку к собеседованиям и карьеру в IT — так, чтобы было понятно и полезно.

Хочешь закрепить знания на практике?

Решай задачи на Algolit — интерактивная платформа для обучения

Начать бесплатно →