Приведи пример использования unowned в Swift

Ответ

unowned — это модификатор захвата ссылки, который не увеличивает счетчик сильных ссылок (Retain Count), но предполагает, что захваченный объект будет существовать на протяжении всего времени жизни захватившей его сущности (например, замыкания или другого объекта). В отличие от weak, unowned ссылка не является опциональной. Попытка доступа к unowned ссылке после освобождения объекта приводит к крашу приложения (dangling pointer).

Типичный use-case: Циклическая связь, где время жизни одного объекта гарантированно короче или равно времени жизни другого.

Пример:

class Customer {
    let name: String
    var card: CreditCard? // У Customer МОЖЕТ быть карта
    init(name: String) { self.name = name }
}

class CreditCard {
    let number: String
    unowned let customer: Customer // У карты ВСЕГДА есть владелец
    init(number: String, customer: Customer) {
        self.number = number
        self.customer = customer
    }
}

// Использование
var john: Customer? = Customer(name: "John Appleseed")
john!.card = CreditCard(number: "1234-5678", customer: john!)
// CreditCard ссылается на Customer через unowned.
john = nil // Customer освобождается, CreditCard также освобождается.
// Цикл не создан, утечки нет.

Ключевые отличия от weak:

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

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

Ответ 18+ 🔞

А, ну это про unowned, да? Слушай, это ж как взять в заложники соседа, но без наручников — просто пальцем на него показывать и орать «он никуда не денется!». Ну, типа, ссылка есть, а счётчик не увеличивается, блядь. Красиво, да? Ха-ха!

Вот представь: есть у тебя Customer — клиент, и CreditCard — его карта. Карта без клиента — это как водка без закуски, неебически бессмысленная хуйня. Так вот, в карте мы клиента храним как unowned. Это значит: «Мужик, я на тебя ссылаюсь, но не держу тебя силой. Только, чур, не сдыхать раньше меня, а то я твоё имя вспомню — и приложение нахуй рухнет, в рот меня чих-пых!»

class Customer {
    let name: String
    var card: CreditCard?
    init(name: String) { self.name = name }
}

class CreditCard {
    let number: String
    unowned let customer: Customer // Смотри, какая наглая морда! Ссылается, но не удерживает.
    init(number: String, customer: Customer) {
        self.number = number
        self.customer = customer
    }
}

Работает это так: пока клиент жив — всё пиздато. Карта может орать «эй, customer.name!» и получать ответ. Но стоит клиенту (john) стать nil... Ой, ёпта. Карта тоже освобождается, потому что её больше никто не держит. Но если бы она чудом выжила и попыталась достучаться до customer — ей бы пиздец, краш мгновенный, dangling pointer, всё дела. Это не как weak, который трусливо становится nil — тут тебе сразу билет в крематорий.

Короче, отличие от weak — как между трусом и самоубийцей:

  • weak — ссылка-трус. Объект умер? weak говорит: «Ой, бля, его нет, я nil, делайте что хотите». Опциональная она, мудя.
  • unowned — ссылка-самоубийца. Объект умер? А unowned делает вид, что он ещё тут, лезет к нему в карман — и БАМ! Вылетает нахуй с ошибкой доступа к памяти. Неопциональная, блядь, самоуверенная скотина.

Когда это юзать? Да когда на сто пятьсот процентов уверен, что один объект переживёт другой. Типа, дочерний объект, который без родителя — просто кусок говна. Родитель умер — и дочернему пизда, но он об этом и не узнает, потому что умрёт вместе с ним. Главное — не проебаться с этим, а то будет тебе не циклическая зависимость, а циклический пиздец.