Всем привет! Сегодня разберем одну из фундаментальных тем в 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 подробно поговорим в будущих постах.