В каких случаях в Swift используется weak-ссылка?

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

Ответ

Ключевое слово weak используется для объявления слабых ссылок, которые не увеличивают счетчик сильных ссылок (strong reference count) ARC. Это основной механизм предотвращения циклов сильных ссылок (strong retain cycles), приводящих к утечкам памяти.

Типичные случаи применения:

  1. Делегаты (Delegates) и Data Sources:

    class ViewController: UIViewController {
        weak var delegate: MyViewControllerDelegate? // Ссылка на делегата должна быть weak
    }

    Объект не должен "владеть" своим делегатом.

  2. Замыкания (Closures), захватывающие self:

    class DataLoader {
        func loadData(completion: @escaping (Result<Data, Error>) -> Void) {
            URLSession.shared.dataTask(with: url) { [weak self] data, _, error in
                // Используем weak self, чтобы DataLoader мог освободиться
                self?.handleResponse(data: data, error: error)
                completion(...)
            }.resume()
        }
    }
  3. Двунаправленные связи в родительско-дочерних отношениях, где дочерний объект ссылается на родительский.

Свойства weak-ссылок:

  • Автоматическое обнуление (Zeroing): Когда объект, на который она указывала, освобождается, weak-ссылка автоматически становится nil.
  • Всегда optional: Weak-ссылки должны быть объявлены как опциональные (var) переменные.
  • Только для классов: Применяется только к ссылочным типам (экземплярам классов).

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