Как weak-ссылка влияет на подсчёт ссылок и жизненный цикл объекта в ARC?

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

Ответ

weak-ссылка не увеличивает счётчик сильных ссылок (retain count) объекта в ARC (Automatic Reference Counting). Это ключевое свойство, которое предотвращает циклы сильных ссылок (retain cycles).

Принцип работы:

  1. Нет удержания: weak-ссылка не мешает ARC освободить объект, когда на него не остаётся сильных ссылок.
  2. Автоматическое обнуление: После освобождения объекта все weak-ссылки на него автоматически устанавливаются в nil. Это предотвращает краши при обращении к «висячим» указателям.

Пример:

class Server {
    let name: String
    init(name: String) { self.name = name; print("(name) создан") }
    deinit { print("(name) удалён") }
}

var primaryServer: Server? = Server(name: "Primary") // Retain count = 1
weak var backupServerRef = primaryServer // Retain count остаётся = 1

primaryServer = nil // Сильных ссылок нет. Вывод: "Primary удалён"
print(backupServerRef) // nil. Безопасно, не вызывает краш.

Типичные сценарии использования:

  • Делегаты (delegates): Почти всегда объявляются как weak, чтобы объект не удерживал своего делегата.
  • Замыкания (closures): Использование [weak self] для предотвращения цикла, когда self удерживает замыкание, а замыкание удерживает self.
  • Родительско-дочерние связи: Дочерний объект может иметь weak-ссылку на родительский.

Важно: weak-ссылки в Swift всегда должны быть опциональными переменными (var) типа, так как они могут стать nil.