В чем разница между модификаторами `unowned` и `unowned(unsafe)` в Swift?

«В чем разница между модификаторами `unowned` и `unowned(unsafe)` в Swift?» — вопрос из категории Управление памятью, который задают на 23% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Оба модификатора создают неудерживающие (non-owning) ссылки, но с разным уровнем безопасности времени выполнения.

unowned (Безопасный)

  • Гарантия: Предполагается, что ссылка всегда будет указывать на существующий объект на протяжении всего времени жизни ссылки.
  • Поведение при обращении к освобожденному объекту: Вызовет предсказуемый краш с сообщением Fatal error: Attempted to read an unowned reference.... Это помогает отлаживать логические ошибки.
  • Использование: Когда время жизни ссылки и объекта четко связано (например, кредитор unowned гарантированно освобождается раньше, чем должник).
class Customer {
    let id: String
    var card: CreditCard?
    init(id: String) { self.id = id }
}

class CreditCard {
    let number: String
    unowned let customer: Customer // Карта не может существовать без Клиента
    init(number: String, customer: Customer) {
        self.number = number
        self.customer = customer
    }
}

unowned(unsafe) (Небезопасный)

  • Гарантия: Нет никаких гарантий. Вы как разработчик берете на себя ответственность за то, что объект жив.
  • Поведение при обращении к освобожденному объекту: Неопределенное поведение (Undefined Behavior). Может произойти краш, может вернуться мусорное значение, что приводит к тонким и сложным для отладки ошибкам.
  • Использование: Только для экстремальной оптимизации в коде, критичном к производительности, где вы абсолютно уверены в жизненном цикле объектов (например, при низкоуровневом взаимодействии с C). В обычной разработке на Swift почти никогда не нужен.