Sobes.tech
Middle

¿Qué tipos de enlaces existen en Swift?

sobes.tech AI

Respuesta de la IA

En Swift, existen tres tipos principales de referencias:

  1. Referencia Fuerte (Strong Reference):

    • Aumenta el contador de referencias del objeto.
    • Previene la desasignación del objeto mientras exista al menos una referencia fuerte.
    • Es el tipo de referencia por defecto en Swift.
    • La causa principal de ciclos de referencias fuertes.
  2. **Referencia Débil (Weak Reference):

    • No aumenta el contador de referencias.
    • Permite la desasignación del objeto si ya no hay referencias fuertes.
    • Se declara usando la palabra clave weak.
    • Siempre es opcional (Optional), ya que el objeto referenciado puede ser nil.
    • Se usa para prevenir ciclos de referencias fuertes, cuando una instancia puede existir independientemente de otra.
    class Person {
        let name: String
        weak var apartment: Apartment? // Referencia débil
        init(name: String) {
            self.name = name
        }
        deinit { print("\(name) desasignado") }
    }
    
    class Apartment {
        let unit: String
        var tenant: Person? // Referencia fuerte normal
        init(unit: String) {
            self.unit = unit
        }
        deinit { print("Apartamento \(unit) desasignado") }
    }
    
    var john: Person?
    var unit4A: Apartment?
    
    john = Person(name: "John Appleseed")
    unit4A = Apartment(unit: "4A")
    
    john!.apartment = unit4A
    unit4A!.tenant = john // Aquí surgiría un ciclo de referencias fuertes sin weak
    
    // Las referencias se anulan, los objetos se desasignan
    john = nil
    unit4A = nil
    
  3. **Referencia No Propia (Unowned Reference):

    • No aumenta el contador de referencias.
    • Permite la desasignación del objeto si ya no hay referencias fuertes.
    • Se declara usando la palabra clave unowned.
    • No es opcional. Se asume que el objeto referenciado siempre existirá mientras exista la instancia que contiene la referencia no propia.
    • Usar una referencia no propia en un objeto que ya fue desasignado causará un error en tiempo de ejecución (crash).
    • Se usa para prevenir ciclos de referencias fuertes, cuando una instancia siempre debe existir mientras otra exista, y no hay posibilidad de que uno sea nil independientemente del otro (por ejemplo, en enlaces self en cierres).
    class Customer {
        let name: String
        var card: CreditCard?
        init(name: String) {
            self.name = name
        }
        deinit { print("\(name) desasignado") }
    }
    
    class CreditCard {
        let number: UInt64
        unowned let customer: Customer // Referencia no propia
        init(number: UInt64, customer: Customer) {
            self.number = number
            self.customer = customer
        }
        deinit { print("Tarjeta #\(number) desasignada") }
    }
    
    var john: Customer? = Customer(name: "John Appleseed")
    john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)
    
    // Si se anula el cliente, la tarjeta que hace referencia a él con unowned,
    // se volverá inválida, pero no causará ciclo.
    john = nil // Ambos objetos se desasignan
    

La elección entre weak y unowned depende de la naturaleza de la relación entre los objetos: usa weak cuando un objeto puede existir sin el otro (Person sin Apartment), y unowned cuando un objeto siempre debe existir mientras exista el otro (CreditCard siempre pertenece a Customer).