Middle
Какво е unowned в езика Swift и как се използва?
sobes.tech AI
Отговор от AI
Несобствена препратка (слабо косвено владение) в Swift се използва за избягване на цикли на силно владение (retain cycles), когато два обекта силно се позовават един на друг, предотвратявайки тяхното освобождаване от паметта.
Характеристики на unowned:
- Гарантира, че обектът, към който се отнася
unownedпрепратката, винаги съществува до момента на използването ѝ. - Ако се опитате да получите достъп до
unownedпрепратка след като свързаният обект е освободен, ще настъпи грешка по време на изпълнение (runtime crash). - Използва се, когато жизненият цикъл на рефериращия обект не е по-дълъг от този на обекта, към който се отнася. Тоест,
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.