Middle
¿Qué es unowned en el lenguaje Swift y cómo se usa?
sobes.tech AI
Respuesta de la IA
La referencia no poseída (posesión indirecta débil) en Swift se utiliza para evitar ciclos de posesión fuerte (retain cycles), cuando dos objetos se refieren mutuamente de manera fuerte, impidiendo su liberación de la memoria.
Características de unowned:
- Garantiza que el objeto al que se refiere la referencia
unownedsiempre existe hasta el momento de usar esa referencia. - Si se intenta acceder a la referencia
unowneddespués de que el objeto relacionado haya sido liberado, ocurrirá un error en tiempo de ejecución (runtime crash). - Se usa cuando el ciclo de vida del objeto que hace referencia no es más largo que el ciclo de vida del objeto al que se refiere. Es decir, la referencia con
unownedno hace que el objeto sea fuerte.
Ejemplo de uso en captura de cierre:
class Customer {
let name: String
var card: CreditCard?
init(name: String) {
self.name = name
}
deinit {
print("\(name) está siendo desalojado")
}
}
class CreditCard {
let number: UInt64
unowned let customer: Customer // Referencia no poseída a Customer
init(number: UInt64, customer: Customer) {
self.number = number
self.customer = customer
}
deinit {
print("Tarjeta #\(number) está siendo desalojada")
}
}
var john: Customer? // Customer opcional para permitir liberación
john = Customer(name: "John Appleseed")
john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)
// Asignar nil a john llevará a liberar Customer y Card,
// ya que no hay ciclo de posesión fuerte
john = nil
Otro ejemplo - uso de unowned en lista de captura de cierre:
class HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = { [unowned self] in // Uso de 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) está siendo desalojado")
}
}
var paragraph: HTMLElement? // Elemento HTML opcional
paragraph = HTMLElement(name: "p", text: "hola mundo")
print(paragraph!.asHTML())
// Asignar nil liberará HTMLElement, ya que la clausura no lo mantiene fuertemente
paragraph = nil
La elección entre unowned y weak depende de si la referencia puede ser nil durante la vida del objeto. Si la referencia nunca puede ser nil antes de que el objeto sea liberado, usa unowned. Si puede serlo, usa weak.