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

Ответ

Нет, наличие 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.

Ответ 18+ 🔞

А, слушай, смотри, вот этот твой вопрос про unowned — это же классика, блядь! Прям как в анекдоте про Герасима и Муму, только с памятью. Так вот, запомни раз и навсегда: unowned — это не владеющая ссылка, сука! Она нихуя не удерживает объект в памяти, ей вообще похуй на твой retain count.

Представь, что сильная ссылка — это ты, который держит собаку за поводок. А 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 // Бросаешь поводок нахуй.
// В консоли: "John освобожден" — собака-то сбежала!
// А unownedReference теперь тыкает в освобождённую память. Пиздец.
// Сделай теперь print(unownedReference.name) — получишь краш, ебаный в рот!

Так когда эту штуку использовать-то, спросишь? Да когда уверен, как в заднице, что объект проживёт дольше, чем твоя на него ссылка! Ну, типа, делегаты всякие. Или чтобы циклы сильных ссылок разорвать, но если через weak — там ещё опционалы разворачивать, заёбываться... А тут — раз и готово, но если ошибёшься в логике — чих-пых тебя в сраку с крашем!

Короче, unowned — это как ходить по охуенно тонкому льду. Красиво, быстро, но если провалишься — всем пизда.