Sobes.tech
Middle

¿En qué consiste la diferencia entre enlaces Wick y enlaces Anound?

sobes.tech AI

Respuesta de la IA

La referencia débil (weak) es una referencia que no posee la propiedad de aumentar el contador de referencias del objeto. Se usa para prevenir ciclos de referencias fuertes, por ejemplo, entre un delegado y su propietario. Si el objeto al que apunta la referencia débil se desasigna, la referencia débil automáticamente se vuelve nil.

La referencia no poseedora (unowned) también es una referencia que no aumenta el contador de referencias del objeto. La diferencia con weak es que unowned no puede ser opcional (Optional) y siempre debe apuntar a un objeto existente. Si el objeto al que apunta la referencia unowned se desasigna antes de que la referencia deje de existir, intentar acceder a esa referencia provocará un error en tiempo de ejecución (error fatal). Se usa donde el ciclo de vida del objeto relacionado es garantizado que sea más largo o igual al ciclo de vida del objeto con la referencia unowned (por ejemplo, en un ciclo de referencias fuertes donde uno de los objetos tiene un ciclo de vida claramente definido).

Comparación:

Característica weak unowned
No posee
Incrementa el conteo No No
Puede ser nil Sí (se nulifica automáticamente) No (debe apuntar a un objeto)
Seguridad Más segura en caso de desasignación Menos segura (error fatal al acceder a un objeto desasignado)
Tipo Debe ser opcional No puede ser opcional (por defecto)
Uso Prevención de ciclos de referencias fuertes donde el objeto puede dejar de existir antes Prevención de ciclos de referencias fuertes donde el objeto garantiza su existencia

Ejemplo de uso de weak para prevenir ciclos de referencias fuertes:

class Person {
    let name: String
    weak var apartment: Apartment? // referencia débil para evitar ciclo de retención

    init(name: String) {
        self.name = name
        print("\(name) está siendo inicializado")
    }

    deinit {
        print("\(name) está siendo desinicializado")
    }
}

class Apartment {
    let unit: String
    var occupant: Person?

    init(unit: String) {
        self.unit = unit
        print("Apartamento \(unit) está siendo inicializado")
    }

    deinit {
        print("Apartamento \(unit) está siendo desinicializado")
    }
}

Ejemplo de uso de unowned en el contexto de capturar self en un cierre:

class HTMLElement {
    let name: String
    let text: String?

    lazy var asHTML: () -> String = {
        [unowned self] in // self no poseedor para evitar ciclo de retención con el cierre
        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 desinicializado")
    }
}