Какую проблему решают weak и unowned ссылки в Swift?

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

Ответ

weak и unowned ссылки решают проблему сильных циклических ссылок (strong reference cycles), которые приводят к утечкам памяти, так как Automatic Reference Counting (ARC) не может освободить объекты, ссылающиеся друг на друга.

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

  • weak — создает опциональную (Optional) ссылку, которая не увеличивает счетчик ссылок (retain count). Становится nil, когда целевой объект освобождается.
  • unowned — создает неопциональную ссылку, которая также не увеличивает счетчик ссылок. Предполагает, что целевой объект будет существовать на протяжении всего времени жизни ссылки. Обращение к unowned ссылке после освобождения объекта вызывает краш.

Пример проблемы и решения:

class Person {
    var apartment: Apartment? // Сильная ссылка -> цикл
}

class Apartment {
    var tenant: Person? // Сильная ссылка -> цикл
}
// Создание цикла:
var john: Person? = Person()
var unit4A: Apartment? = Apartment()
john?.apartment = unit4A
unit4A?.tenant = john // Цикл! Объекты никогда не освободятся.

// Решение с weak:
class Apartment {
    weak var tenant: Person? // Weak ссылка разрывает цикл
}

Когда использовать:

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