Middle
Swift-ის ენაში unowned რა არის და როგორ გამოიყენება?
sobes.tech AI
პასუხი AI-სგან
Swift-да Unowned referens (злабое косвенное владение) — это механизм, используемый для предотвращения циклов сильного владения (retain cycles), когда два объекта ссылаются друг на друга, что мешает их освобождению из памяти.
Особенности unowned:
- Гарантирует, что объект, на который ссылается
unownedссылка, всегда существует до момента обращения к ней. - Попытка обращения к
unownedссылке после освобождения связанного объекта приведет к ошибке времени выполнения (runtime crash). - Используется, когда жизненный цикл объекта, на который ссылается
unowned, не длиннее жизненного цикла объекта, который ссылается. То есть,unownedне делает объект сильнее.
Пример использования в захвате замыкания:
class Customer {
let name: String
var card: CreditCard?
init(name: String) {
self.name = name
}
deinit {
print("\(name) освобожден")
}
}
class CreditCard {
let number: UInt64
unowned let customer: Customer // Unowned ссылка на Customer
init(number: UInt64, customer: Customer) {
self.number = number
self.customer = customer
}
deinit {
print("Карта #\(number) освобожден")
}
}
var john: Customer? // Опциональный Customer
john = Customer(name: "John Appleseed")
john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)
// Присвоение nil к john приведет к освобождению Customer и Card,
// так как нет цикла сильного владения
john = nil
Другой пример — использование unowned в списке захвата замыкания:
class HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = { [unowned self] in // Использование unowned self
if let text = self.text {
return "<\(self.name)>\(text)</\(self.name)>"
} else {
return "<\(self.name) />"
}
}
init(name: String, text: String? = nil) {
self.name = name
self.text = text
}
deinit {
print("\(name) освобожден")
}
}
var paragraph: HTMLElement? // Опциональный HTML элемент
paragraph = HTMLElement(name: "p", text: "hello world")
print(paragraph!.asHTML())
// Присвоение nil освободит HTMLElement, так как замыкание не удерживает его сильно
paragraph = nil
Выбор между unowned и weak зависит от того, может ли ссылка стать nil в течение жизни объекта. Если ссылка никогда не может стать nil до освобождения объекта, используйте unowned. Если может — используйте weak.