Назад к вопросам
Middle
100
questionbank

В чем заключается разница между 'weak' и 'unowned' в Swift?

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

weak и unowned используются для разрешения циклических ссылок, но отличаются по своему поведению и применению.

Свойство 'weak' 'unowned'
Тип Опционал (Optional) Не опционал
Lifetime Может стать nil Гарантированно имеет значение
Гарантия существования Нет Да, до окончания Scope
Применение Когда возможна ситуация, что связанный объект будет деаллоцирован первым. Когда связанный объект будет деаллоцирован либо одновременно с текущим, либо позже.
Пример Делегат (delegate) Связь Родитель-Ребенок (Parent-Child)

weak:

  • Используется, когда один объект может существовать без ссылки на другой, или когда одному из объектов разрешено быть nil.
  • Автоматически становится nil, когда объект, на который он ссылается, деаллоцируется.
  • Должен быть объявлен как опциональный тип.
class Person {
    let name: String
    var apartment: Apartment?

    init(name: String) { self.name = name }
    deinit { print("\(name) is being deinitialized") }
}

class Apartment {
    let unit: String
    weak var tenant: Person? // cyclic reference solved with weak

    init(unit: String) { self.unit = unit }
    deinit { print("Apartment \(unit) is being deinitialized") }
}

var john: Person? = Person(name: "John Appleseed")
var unit4A: Apartment? = Apartment(unit: "4A")

john?.apartment = unit4A
unit4A?.tenant = john // No strong reference cycle

john = nil // Person object is deallocated
// unit4A?.tenant is now nil

unit4A = nil // Apartment object is deallocated

unowned:

  • Используется, когда одному объекту принадлежит другой, и оба должны существовать одновременно или связанный объект переживет текущий.
  • Гарантируется, что всегда имеет значение. При попытке доступа после деаллокации объекта произойдет сбой выполнения (runtime error).
  • Объявляется как не опциональный тип.
class Customer {
    let name: String
    var card: CreditCard?

    init(name: String) { self.name = name }
    deinit { print("\(name) is being deinitialized") }
}

class CreditCard {
    let number: UInt64
    unowned let customer: Customer // cyclic reference solved with unowned

    init(number: UInt64, customer: Customer) {
        self.number = number
        self.customer = customer
    }
    deinit { print("Card #\(number) is being deinitialized") }
}

var john: Customer? = Customer(name: "John Appleseed")
john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!) // No strong reference cycle

john = nil // Customer and CreditCard objects are deallocated

Выбор между weak и unowned зависит от того, имеет ли связанный объект возможность стать nil в течение жизни текущего объекта. Если да, используйте weak. Если нет, используйте unowned.