Будет ли объект освобожден из памяти, если на него существует unowned-ссылка?

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

Ответ

Нет, наличие unowned-ссылки само по себе не удерживает объект в памяти. Unowned — это не владеющая (weak) ссылка, которая не увеличивает счетчик сильных ссылок (retain count). Объект будет освобожден, как только на него не останется сильных (strong) ссылок, даже если существуют unowned-ссылки.

Ключевое отличие от weak: Unowned предполагает, что объект будет существовать дольше, чем ссылка на него. Если объект освободится, обращение к unowned-ссылке вызовет краш приложения.

Пример, демонстрирующий освобождение:

class Person {
    let name: String
    init(name: String) { self.name = name }
    deinit { print("(name) освобожден") }
}

var strongPerson: Person? = Person(name: "John") // Сильная ссылка (retain count = 1)
unowned let unownedReference = strongPerson! // Не увеличивает retain count

strongPerson = nil // Сильная ссылка обнулена, retain count становится 0
// В консоли выведется: "John освобожден"
// Теперь `unownedReference` указывает на освобожденную память (невалидна)
// Попытка доступа `print(unownedReference.name)` приведет к крашу.

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

  • Когда жизненный цикл ссылающегося объекта короче или равен жизненному циклу целевого объекта (классический пример: делегат).
  • Когда вы уверены, что целевой объект никогда не будет nil в течение времени использования ссылки.
  • Для устранения циклов сильных ссылок, где weak привел бы к необходимости постоянной проверки на nil.