Sobes.tech
Middle

¿Para qué sirve el tipo de referencias unowned?

sobes.tech AI

Respuesta de la IA

Las referencias unowned son necesarias para resolver referencias cíclicas (retains cycles) entre objetos, cuando ambos objetos tienen una referencia fuerte entre sí, pero uno de los objetos tiene un ciclo de vida más corto o igual al otro.

unowned se usa cuando se sabe que el objeto referenciado no será nil durante toda la vida del objeto que contiene la referencia. A diferencia de weak, al acceder a una referencia unowned no se usa Optional. Si el objeto al que se refiere unowned es desasignado antes que el objeto con la referencia unowned, ocurrirá un crash.

Ejemplo de uso en closures:

class Person {
    let name: String
    var apartment: Apartment?

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

    deinit {
        print("\(name) is being deinitialized")
    }
}

class Apartment {
    let unit: String
    // Usamos unowned porque se sabe que
    // Apartment no puede existir sin Person
    // (en este contexto). Person puede ser nil,
    // pero si Apartment existe, Person también existe.
    unowned let tenant: Person?

    init(unit: String, tenant: Person?) {
        self.unit = unit
        self.tenant = tenant
        print("Apartment \(unit) is being initialized")
    }

    deinit {
        print("Apartment \(unit) is being deinitialized")
    }
}

var john: Person?
var unit4A: Apartment?

john = Person(name: "John Appleseed")
// En este ejemplo, tenant puede ser nil, por eso
// se usa unowned optional
unit4A = Apartment(unit: "4A", tenant: john)

john!.apartment = unit4A

// Rompemos las referencias fuertes para verificar la desasignación
john = nil
unit4A = nil

En este ejemplo, Person tiene una referencia fuerte a Apartment (var apartment: Apartment?). Apartment podría tener una referencia fuerte a Person, lo que causaría un ciclo. Sin embargo, dado que en este contexto Apartment no puede existir sin Person (que lo alquila), la referencia desde Apartment a Person se hace unowned. De esta forma, al poner a john = nil, Person se desasigna, y a su vez (ya que no hay referencias fuertes a Apartment) también se desasigna Apartment.

Diferencias principales con weak:

  • Ciclo de vida: unowned se usa cuando el objeto referenciado tiene un ciclo de vida igual o más largo. weak se usa cuando el objeto referenciado puede ser desasignado antes.
  • Optional: unowned no es Optional (a menos que se declare como unowned optional). weak siempre es Optional.
  • Seguridad: Acceder a una propiedad con referencia unowned a un objeto ya desasignado causará un crash. Acceder a una referencia weak devolverá nil.

Por lo tanto, unowned es una referencia no propietaria (non-owning) que se usa cuando se garantiza la existencia del objeto referenciado mientras exista el objeto con la referencia unowned.