Что делает ARC в Run Time?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
ARC (Automatic Reference Counting) в Runtime
ARC — это автоматический механизм управления памятью в Swift и Objective-C. Вместо сборщика мусора, ARC отслеживает и автоматически освобождает память через подсчёт ссылок.
Как работает подсчёт ссылок
Когда объект создаётся, его reference count = 1. При каждом новом присваивании переменной счётчик увеличивается на 1. Когда переменная выходит из scope или переприсваивается, счётчик уменьшается на 1. Когда счётчик достигает 0, объект немедленно освобождается из памяти.
class Person {
let name: String
init(name: String) {
self.name = name
print("Person \(name) init")
}
deinit {
print("Person \(name) deinit")
}
}
// Демонстрация ARC
var person1: Person? = Person(name: "Alice") // refCount = 1
var person2 = person1 // refCount = 2
person1 = nil // refCount = 1
person2 = nil // refCount = 0 → deinit вызывается
Strong vs Weak ссылки
Strong ссылка — увеличивает reference count. Это используется по умолчанию. Если все ссылки на объект strong, объект остаётся в памяти.
Weak ссылка — НЕ увеличивает reference count. Используется для избежания retain cycles. Weak ссылка автоматически становится nil когда объект деинициализируется.
class Parent {
let name: String
var child: Child?
init(name: String) {
self.name = name
}
deinit {
print("Parent \(name) deinitialized")
}
}
class Child {
let name: String
weak var parent: Parent? // Weak чтобы избежать цикла
init(name: String) {
self.name = name
}
deinit {
print("Child \(name) deinitialized")
}
}
// Без weak была бы утечка памяти (retain cycle)
var parent: Parent? = Parent(name: "John")
var child: Child? = Child(name: "Jane")
parent?.child = child
child?.parent = parent
parent = nil // Parent деинициализируется
child = nil // Child деинициализируется
Unowned ссылки
Unowned похожа на weak, но не опциональна. Используется когда дочерний объект НИКОГДА не будет существовать без родителя.
class CreditCard {
let number: String
unowned let owner: Person // owner никогда не null
init(number: String, owner: Person) {
self.number = number
self.owner = owner
}
}
let person = Person(name: "Bob")
let card = CreditCard(number: "1234", owner: person)
// person всегда существует пока существует card
Capture Lists в Closures
Closure'ы могут создавать retain cycle'ы, если захватывают self. Используй capture list для управления::
class ViewController: UIViewController {
var name = "ViewController"
func setupButton() {
button.addAction(UIAction { [weak self] _ in
// weak self избегает retain cycle
guard let self else { return }
print(self.name)
}, for: .touchUpInside)
}
}
Runtime процесс
- Compile time — компилятор вставляет retain и release вызовы
- Runtime — Objective-C runtime отслеживает refCount для каждого объекта
- Deallocation — когда refCount = 0, вызывается deinit и память освобождается
Это означает, что в отличие от GC, память освобождается НЕМЕДЛЕННО, что крайне важно для мобильных устройств с ограниченными ресурсами.