Как ARC автоматически расставляет retain и release?

«Как ARC автоматически расставляет retain и release?» — вопрос из категории Управление памятью, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

ARC (Automatic Reference Counting) автоматически вставляет вызовы retain и release, отслеживая время жизни сильных (strong) ссылок на объекты.

Правила вставки:

  • retain: Вставляется при присваивании объекта сильной ссылке (переменной, свойству, константе). Увеличивает счетчик ссылок.
  • release: Вставляется в двух случаях:
    1. Когда сильная ссылка перезаписывается другим значением (или nil).
    2. Когда сильная ссылка выходит из области видимости (например, завершается функция).

Пример трассировки:

class MyClass {}

func example() {
    // Область видимости начинается
    var obj1: MyClass? = MyClass() // ARC: retain для нового объекта
    var obj2: MyClass? = obj1      // ARC: retain (присваивание obj1 в obj2)

    obj1 = nil                     // ARC: release для obj1
    // Объект еще жив, так как на него ссылается obj2

    obj2 = MyClass()               // ARC: release для старого объекта, retain для нового
    // Старый объект уничтожается здесь (счетчик = 0)
} // ARC: release для obj2 (для нового объекта) при выходе из области видимости

Особые случаи:

  • weak ссылки: Не вызывают retain, поэтому не влияют на счетчик. ARC автоматически обнуляет (nil) weak-переменную после release последней сильной ссылки.
  • unowned ссылки: Также не вызывают retain, но не обнуляются. Ответственность за обеспечение времени жизни объекта лежит на программисте.
  • Циклы сильных ссылок: ARC не может их разорвать, что приводит к утечкам памяти. Решение — использование weak или unowned.