Добавить объявление

ARC в Swift: как работает автоматическое управление памятью

Всем привет! Сегодня разберем одну из фундаментальных тем в iOS-разработке: управление памятью с помощью ARC. Понимание этого механизма критически важно для создания стабильных приложений без утечек памяти.

Что такое ARC:


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

Пример:

class User {
let name: String

init(name: String) {
self.name = name
}
}

var user1: User? = User(name: "Иван") // Счетчик ссылок: 1
var user2: User? = user1 // Счетчик ссылок: 2
user1 = nil // Счетчик ссылок: 1
user2 = nil // Счетчик ссылок: 0, память освобождена

Главная проблема - циклы сильных ссылок:


Самая распространенная ошибка: создание retain cycles, когда два объекта держат друг друга сильными ссылками и не могут быть освобождены.

Пример:

class Profile {
var settings: Settings?
}

class Settings {
var profile: Profile?
}

let profile = Profile() // Счетчик ссылок: 1
let settings = Settings() // Счетчик ссылок: 1

profile.settings = settings // Счетчик ссылок: 2, Profile держит Settings
settings.profile = profile // Счетчик ссылок: 2, Settings держит Profile

// Оба объекта держат друг-друга и не будут освобождены!

Решение - weak и unowned ссылки:


Weak и unowned ссылки не увеличивают счетчик ссылок объекта.

Weak ссылки:

class Profile {
weak var settings: Settings?
}

class Settings {
weak var profile: Profile?
}

let profile = Profile() // Счетчик ссылок: 1
let settings = Settings() // Счетчик ссылок: 1

profile.settings = settings // Счетчик ссылок не увеличивается
settings.profile = profile // Счетчик ссылок не увеличивается

// Теперь объекты могут быть освобождены

Unowned ссылки:

class CreditCard {
unowned let owner: Customer

init(owner: Customer) {
self.owner = owner
}
}

class Customer {
let name: String

init(name: String) {
self.name = name
}
}

let customer = Customer(name: "Artem") // Счетчик ссылок: 1
let card = CreditCard(owner: customer) // Счетчик ссылок: 1 (не изменился!)

// Теперь объекты могут быть освобождены

Разница между weak и unowned:



Weak:

  • Не увеличивает счетчик ссылок.

  • Автоматически становится nil при удалении объекта.

  • Безопасны в использовании.


Unowned:

  • Не увеличивает счетчик ссылок.

  • Не становятся nil (вызовут краш при обращении к удаленному объекту).

  • Используются, когда объект гарантированно существует.

Вывод:


ARC автоматизирует управление памятью, но требует от разработчика понимания работы ссылок. Ключевое правило: weak и unowned ссылки не увеличивают счетчик ссылок, что позволяет разрывать циклы зависимостей. Используйте weak для безопасных связей и unowned только когда уверены в жизненном цикле объектов.

Про внутреннюю механику работы weak-ссылок через Side Tables подробно поговорим в будущих постах.
21.12.2025 19 536